一、线程的概念
先说进程的概念:进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是线程的容器。是程序的实体。
而线程就是轻量级的进程,是程序执行的最小单位。
打个比方,进程是一家公司对外提供服务,线程就可以是公司里的各个部门或员工。线程各司其职,相互协作,使用公共资源等。
二、线程的状态
查看Thread代码,可以看到
public enum State { NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED; }
源代码中列举了六个线程的状态:
new表示线程刚刚创立还没开始执行,对应的terminated表示线程的结束
线程执行时处于runnable,一切资源都已经准备好,当线程碰到同步代码块,进入blocked阻塞状态,线程暂停执行,直到获得锁。
waiting和timed_waiting都是等待状态,区别是一个是有时间的等待,一个是需要特殊事件(如wait,join)的等待,完成等待后重新进入runnable
三、线程的基本操作
1.新建
(1)继承Thread
(2)重载runnable
2.终止
Thread.stop(),不推荐使用,stop是直接停止,释放所有锁,可能造成数据不一致的情况
3.中断
线程中断不会使线程退出,而是告诉线程有人希望你退出,具体退出由线程自己决定
Thread.interrupted(); //判断有没有中断并清除当前中断状态
Thread.isInterrupted();//判断有没有中断
Thread.interrupt(); //中断
public static void main(String[] args) throws InterruptedException { Thread t=new Thread(){ @Override public void run() { while(true) { System.out.println("run"); if(Thread.currentThread().isInterrupted()) { System.out.println("over"); break; } } } }; t.start(); Thread.sleep(100); t.interrupt(); }
在上面的例子里线程是永久运行的直到得到中断标志
另外,Thread.sleep()会抛出InterruptedException中断异常,当在睡眠时被中断。值得注意的是异常抛出后会清理中断状态
4.等待和通知
notify() notifyAll() wait() 不属于Thread类,属于Object类。一般在synchronize中使用。
当在一个对象上使用wait()时,线程就会在对象上等待,notify随机唤醒一个在对象上等待的线程,notifyAll唤醒所有。
wait方法前必须获得对象的监视器,wait之后释放监视器,这里和sleep不同。
public class threadDemo { static Object obj=new Object(); class waitThread extends Thread{ @Override public void run() { synchronized(obj) { System.out.println(System.currentTimeMillis()+"w start"); try { obj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(System.currentTimeMillis()+"w end"); } } } class notifyThread extends Thread{ @Override public void run() { synchronized(obj) { System.out.println(System.currentTimeMillis()+"n start"); obj.notifyAll(); System.out.println(System.currentTimeMillis()+"n end"); } } } public static void main(String[] args) throws InterruptedException { waitThread w=new threadDemo().new waitThread(); notifyThread n=new threadDemo().new notifyThread(); w.start(); Thread.sleep(1000); n.start(); } }
5.挂起和继续执行
suspend() resume() 已废弃,不推荐使用
6.等待结束和谦让
join() yeild()
有时候一个线程的输入需要依赖另一个线程的输出,这时候就需要线程的顺序执行,join()就可以实现顺序执行
public static int i=0; class waitThread extends Thread{ @Override public void run() { for(i=0;i<1000;i++){} } } public static void main(String[] args) throws InterruptedException { waitThread w=new threadDemo().new waitThread(); w.start(); w.join(); System.out.println(i); }
这里主线程等待w线程执行完才输出i的值为1000,如果没有join的话,i值几乎不可能是1000。
join的本质还是用wait和notify使调用线程等着在现在线程的实例上。
yeild()让当前线程让出cup。