Thread提供了一个线程等待另一个线程执行的方法,当在某个程序的执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到被join()方法加入的线程执行完为止.
Join():等待join线程执行完成
Join(long millis):等待join线程完成时间最多为millis毫秒,如果在millis毫秒内该线程还没有结束,则不再等待.
5.线程同步;
5.1,线程安全问题
这个案例中,你和你老婆相当于俩个并发线程,都在修改存款,系统在判断你的条件满足后正好执行线程切换,切换给你老婆去执行,所以会产生问题.
5.2,同步代码块
为了解决这个问题,java的多线程引入了同步监视器来解决这个问题.
同步监视器的目的:组织2个线程对同一个共享资源进行并发访问.
synchronized(obj) {
//此处的代码就是同步代码块
}
上述obj就是同步监视器,当线程开始执行同步代码块之前,必须获得对同步监视器的锁定.
注意:任何时刻只能有一个线程可以获得对同步监视器的锁定,当同步代码块执行完毕后,该线程会释放对该同步代码块的锁定.
5.3,同步方法
即使用synchronized修饰某个方法(非static修饰),则该方法就是同步方法,无需指定同步监视器,同步方法的同步监视器是this,也就是调用该方法的对象.
5.4,释放同步监视器的锁定
线程在如下情况会释放对同步监视器的锁定:
--当线程的同步方法,同步代码块执行结束,会释放对同步监视器的锁定.
--当前线程在同步代码块,同步方法中出现了break,return终止了该代码块,方法的执行,会释放对同步监视器的锁定.
--当前线程在同步代码块,同步方法中出现了未处理的Exception,Error,导致了该方法,代码块异常结束,会释放同步监视器的锁定.
--当前线程在同步代码块,同步方法中执行了同步监视器对象的wait(),则当前线程暂停,并释放同步监视器的锁定.
在如下所示的情况下,线程不会释放对同步监视器的锁定:
--线程在执行同步代码块,同步方法时,程序调用Thread.sleep();Thread.yield();暂停当前线程的执行,当前线程不会释放同步监视器的锁定.
5.5,死锁
当2个线程互相等待对方释放同步监视器时就会发生死锁.
5.6,线程池
系统启动一个线程池的成本是比较高的,因为它涉及到与操作系统交互,在这种情况下使用线程池可以很好的提高性能.
线程池在系统启动时即创建了大量空闲的线程,程序将一个Runnable对象或者Callable对象传给线程池,线程池就会启动一个线程来执行他们的run();或者call();当方法结束后,线程不会死亡,而是返回线程池中成为空闲状态,等待下一个对象.
使用Executors工厂类来产生线程池,该工厂类包含如下几个静态方法来创建线程池: