一、线程控制
和线程相关的操作都定义在Thread类中,但在运行时可以获得线程执行环境的信息。比如查看可用的处理器数目(这也行?):
Runtime.getRuntime().availableProcessors();
线程还提供了一些方法用于对线程进行便捷的控制。22222
1、线程睡眠
静态方法Thread.sleep(long millis)强制正在执行的线程暂停进入睡眠状态,进入阻塞状态。睡眠结束后,线程转为就绪状态。
/*自定义的睡眠时间单位为毫秒*/
/*必须要进行异常处理*/
try {
Thread.sleep(lengthOfPause);
} catch(InterruptedException e) {
e.printStacktrace();
}
值得强调的是:
- 线程睡眠是帮助其他所有线程获得运行机会的最好方法;
- 线程睡眠到期自动苏醒,并返回到就绪状态,不是运行状态。然后,sleep()中参数指定的时间是停止运行的最短时间,而无法保证从睡眠苏醒后就开始执行;
- sleep()是静态方法,只能控制当前正在运行的线程;
2、线程让步
yield()方法使当前线程让出CPU占有权,与sleep()类似,但让出时间无法设定。而且yield()使线程进入就绪状态,更利于有同优先级的其它线程获得运行机会。只是实际中,无法保证yield()达到让步目的,比如让步的线程又被JVM选中。
yield()方法不会释放锁标志。实际上,yield()方法对应了如下操作:先检测当前是否有相同优先级的线程处于就绪状态。若有,则把CPU占有权交给此线程;若没有,继续运行原来的线程。所以yield()尝试做的,是把运行机会给同等级的其它线程,而无法让低级别的线程获得。
3、线程加入
在当前线程中调用另一个线程的join()方法,则当前线程转入阻塞状态。直到另一个线程运行结束,阻塞的线程重回就绪状态。
join()是Thread类的非静态方法,还有带有超时限制的重载版本,如t.join(5000)是让线程等待5000ms,超时后,阻塞的进程进入就绪状态。
4、线程优先级
当应用启动时,主线程是创建的第一个用户线程,程序可以创建多个用户线程和守护线程。
当所有的用户线程执行完毕,JVM终止进程。
设置线程的优先级:
/*优先级为1~10*/
Thread t=new MyThread();
/*设置线程优先级*/
t.setPriority(8);
/*获取线程优先级*/
t.getPriority();
t.start();
//只是说优先级更高的线程有更多的机会获得运行,并不保证先于优先级低的线程运行。
守护线程的优先级别是最低的,用于为系统中的其他对象和线程提供服务,例如JVM中的资源自动回收线程。
将一个用户线程设置为守护线程的方法是在线程对象创建之前调用线程对线的setDaemon()方法。
5、线程分组管理
ThreadGroup类
一旦线程加入某个线程组,该线程就一直存在于该线程组中直至死亡,不能中途改变线程所属的组。
二、线程同步
线程调度的意义在于,JVM对运行的多个线程进行系统级别的协调,以避免多个线程争夺有限的资源而导致应用崩溃。
同步是一种防止对共享资源访问导致数据不一致的机制。即当多个线程访问同一个共享资源时,需要确保该资源在一段时间內仅被一个线程访问。
1、锁机制
关键字synchronized为代码块or方法加锁,实现同步。线程在使用临界资源时加锁,拒绝其他线程的访问,直至该线程解锁。
实际上,任何对象都有一个监视器用于加锁和解锁,当synchronized声明的代码块or方法被执行时,说明当前线程已经成功获取了对象监视器上的锁。当正常执行完毕或异常退出时,当前线程所获取的锁会被自动释放
线程可以在一个对象上加多次锁,JVM保证获取锁之前和释放锁之后的变量的值是与主存中的内容同步的。
1、同步方法
使用synchronized声明方法。
当访问某个对象的同步方法,这个对象会加锁!因此当对象的同步方法被某个线程执行时,其他线程无法访问该对象的任何同步方法,但是可以调用其它非同步方法。
当调用一个对象的静态同步方法时,它锁定的是同步方法所在对象对应的Class对象。因此,其他线程不能调用该类的其他静态同步方法,但是可以调用非静态同步方法。
2、同步代码块
使用synchronized声明同步代码块,锁定其所在的对象or特定的对象,还对象作为可执行的标志从而达到同步效果。
3、同步方法是一种粗粒度的并发控制,某一时刻只能有一个线程执行该同步方法。同步代码块是细粒度的并发控制,只会将块中的代码同步,代码块之外的代码可被其他线程同时访问。
使用synchronized要注意:
- synchronized关键字不能继承;
- 定义接口方法时不能使用synchronized;
- 构造方法不能使用synchronized关键字,但可以使用synchronized代码块进行同步;
三、线程协作
线程之间会有协作关系,一起来完成某项任务。如生产者—消费者模式。
多线程可以通过访问和修改同一份资源(对象)来进行交互和通信,只是需要注意线程访问的安全性。当线程所要求的资源不足时,就进入等待状态;而另外的线程则负责在合适的时机发出通知来唤醒等待中的线程。
等待—通知机制是完成线程间同步的基本机制。
1、wait与notify原语
2、生产者-消费者问题
四、线程池
五、线程同步控制的新特征