2.Java 并行程序基础

1.初始线程:线程的基本操作

1.新建线程

2.终止线程

  • stop

造成数据不一致

3.线程中断

1public void Thread.interrupt() // 中断线程 2public boolean Thread.isTnterrupted() // 判断是否被中断 3public static boolean Thread.interrupted() // 判断是否被中断,并清除当前中断状态

4.等待(wait)和通知(notify)

1public final void wait() throws InterruptedException 2public final native void notify() 3// 4public static native void sleep(long millis) throws InterruptedException

Object.wait()和Thread.sleep()方法都可以让线程等待若干时间。除了wait()可以被唤醒外,另外一个主要区别就是wait()方法会释放目标对象的锁,而Thread.sleep()方法不会释放任何资源。

Object.wait()方法并不是可以随便调用的。它必须包含在对应的synchronzied语句中,无论是wait()或者notify()都需要首先获得目标对象的一个监视器。

5.挂起(suspend)和继续执行(resume)线程

suspend() 在导致线程暂停的同时,并不会取释放任何锁资源。

6.等待线程结束(join)和谦让(yield)

join

1public final void join() throws InterruptedException 2public final synchronized void join(long millis) throws InterruptedException

join:一个线程的输入可能非常依赖另外一个或者多个线程的输出,此时这个线程就需要等待依赖线程执行完毕,才能继续执行。

  • join():无限等待,它会一致阻塞当前线程,直到目标线程执行完毕。
  • join(long millis):给出一个最大等待时间,如果超过给定时间目标线程还在执行,当前线程也会因为“等不及了”,而继续往下执行。

join() 的本质是让调用线程 ==wait()== 在当前线程对象实例上

1//核心代码 2while (isAlive()) { 3 wait(0); 4}

它让调用线程在当前线程对象上进行等待。当线程执行完成后,被等待的线程会在退出前调用notifyAll() 通知所有的等待线程继续执行。因此,值得注意的一点是:不要在应用程序中,在Thread对象实例上使用类似wait()或者notify()等方法,因此这很有可能会影响系统API的工作,或者被系统API所影响

yield

public static native void yield();

2. volatile与Java内存模型(JMM)

volatile:使用volatile申明一个变量时,就等于告诉虚拟机,这个变量极有可能会被某些程序或者线程修改。为了确保这个变量被修改后,应用程序范围内的所有线程都能够“看到”这个改动,虚拟机就必须采用一些特殊的手段,保证这个变量的可见性等特点。

注意:volatile并不能代替锁🔒,它也无法保证一些符合操作的原子性。 例如:👇

1public class VolatileTest { 2 3 volatile static int i = 0; 4 5 public static class PlusTask implements Runnable{ 6 public void run(){ 7 for(int k = 0;k<10000;k++){ 8 i++; 9 } 10 } 11 } 12 13 public static void main(String[] args) throws InterruptedException { 14 Thread[] threads = new Thread[10]; 15 for (int i = 0;i<10;i++){ 16 threads[i] = new Thread(new PlusTask()); 17 threads[i].start(); 18 } 19 20 for (int i = 0;i<10;i++){ 21 threads[i].join(); 22 } 23 System.out.println(i); 24 } 25}

volatile 也能保证数据的可见性和有序性

3.分门别类的管理:线程组

1// 创建线程组 2ThreadGroup tg = new ThreadGroup("PrintGroup"); 3// 使用Thread构造方法指定线程所属的县城组 4Thread t = new Thread(tg,new ThreadTest(),"T1");

stop:慎用,它会停止线程组中所有的线程。和Thread.stop()一样。

4.驻守后台:守护线程(Daemon)

比如:垃圾回收线程、JIT线程

与之对应的是用户线程,当一个Java内,只有守护线程时,Java虚拟机就会自然退出。

1public class DaemonDemo { 2 public static class DaemonT extends Thread{ 3 public void run(){ 4 while(true){ 5 System.out.println("I'm alive"); 6 try { 7 Thread.sleep(5000); 8 } catch (InterruptedException e) { 9 e.printStackTrace(); 10 } 11 } 12 } 13 } 14 15 public static void main(String[] args) throws InterruptedException { 16 Thread t = new DaemonT(); 17 t.start(); 18 // 将t设置为守护线程 19 t.setDaemon(true); 20 Thread.sleep(3000); 21 22 } 23}

5.先干重要的事:线程优先级

使用1-10表示线程优先级。一般使用内置的三个静态标量表示:
数字越大则优先级越高。

1/** 2 * The minimum priority that a thread can have. 3 */ 4public final static int MIN_PRIORITY = 1; 5 6/** 7 * The default priority that is assigned to a thread. 8 */ 9public final static int NORM_PRIORITY = 5; 10 11/** 12 * The maximum priority that a thread can have. 13 */ 14public final static int MAX_PRIORITY = 10;

6.线程安全的概念与synchronized

synchronized:是实现线程间的同步。它的工作是对同步的代码加锁,使得每一次,只能有一个线程进入同步块,从而保证线程间的安全性。

用法:

  • 指定加锁对象:对给定对象加锁,进入同步代码前要获得给定对象的锁。
  • 直接作用于实例方法:相当于对当前实例加锁,进入同步前要获得当前实例的锁
  • 直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁。

7.程序中的幽灵:隐蔽的错误

ArrayList 线程不安全 HashMap 线程不安全. ConcurrentHashMap代替

8.初学者常见问题:错误的加锁


参考文献: 《Java高并发设计》

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

如何正确停止Java线程,终止Java线程的三种方法

如何正确停止Java线程,终止Java线程的三种方法在Java中有以下3种方法可以终止正在运行的线程:1.使用退出标志,使线程正常退出,也就是当run()方法完成后线程终止。2.使用stop()方法强行终止线程,但不推荐,该方法已被弃用,原因见后文。3.使用interrupt方法中断线程。以下内容翻译自J

4、jstack查看线程栈信息

1、介绍利用jps、top、jstack命令找到进程中耗时最大的线程,以及线程状态等等,同时最后还可以显示出死锁的线程查找:FoundoneJavaleveldeadlock即可1、jps获得进程号!(https://oscimg.oschina.net/oscnet/da00a309fa6