线程生命周期
new 新建状态
runnable 运行状态
blocked 阻塞状态、等待某个监视器的锁
waiting 冻结状态、无限等待某个监视器的锁
timed-waiting 等待状态、由另一个线程决定等待的时间
terminated 退出状态
线程控制
让run()结束,控制循环让run方法结束
join()
调用join方法的线程对象强制运行,该线程强制运行期间,其他线程无法运行.但是在调用join()方法之前开起的方法可以运行。
import java.util.*; class ThreadTest implements Runnable { public void run() { for(int i=0;i<100;i++) System.out.println(Thread.currentThread().getName()+"running"); } } class ThreadDemo { public static void main(String[] args) { ThreadTest t=new ThreadTest(); Thread t1=new Thread(t,"b"); new Thread(t,"a").start(); //要先start(),因为join()不会调用run方法,它只是强制让该线程执行完才会执行下面的线程。但是在join之前的执行的线程照常执行。 t1.start(); try { t1.join(); //会抛出InterruptedException } catch(InterruptedException e) { e.printStackTrace(); } new Thread(t,"c").start(); } }
多线程安全
当多个线线程同时操作一个类的数据,其结果与单个线程操作的结果一样,说明是同步的、安全的。
不安全的线程
class ThreadTest implements Runnable { private int tickts=100; public void run() { for(;tickts>0;) { try { Thread.sleep(10); } catch(InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" sale No."+tickts--); } } } class ThreadDemo { public static void main(String[] args) { ThreadTest tt=new ThreadTest(); new Thread(tt,"A").start(); new Thread(tt,"B").start(); new Thread(tt,"C").start(); } }
会出现一张票卖两次的情况。
因为当C线程执行到sleep之后丧失了CPU执行权,这时A线程获得执行权将代码执行到了System。然后C又获得了执行权,此时tickts为0的值以被A线程先执行了。
同步代码
class ThreadTest implements Runnable { private int tickts=100; public void run() { for(;tickts>0;) { synchronized(this) //当一个线程执行到这时,就像关了门一样,只要先进去的线程不出来,后面的线程就不能执行该代码块中的内容 { try { Thread.sleep(10); } catch(InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" sale No."+tickts--); } } } } class ThreadDemo { public static void main(String[] args) { ThreadTest tt=new ThreadTest(); new Thread(tt,"A").start(); new Thread(tt,"B").start(); new Thread(tt,"C").start(); } }
线程通信
让A线程执行一段代码,紧接B线程执行一代码,轮回执行。
import java.util.concurrent.locks.*; import java.util.*; class Person { private String name; private String sex; ReentrantLock lock=new ReentrantLock(); Condition jin=lock.newCondition(); Condition chu=lock.newCondition(); private int flag=0; //定义一个标记 public void set(String name,String sex) { lock.lock(); //锁 try { if(flag==1) //如果有值flag为1,为1就不胜存值了,等待输出 { try { jin.await(); //设置线程等待 } catch(InterruptedException e) { e.printStackTrace(); } } this.name=name; this.sex=sex; System.out.println("Setting..........."); flag=1; //存完值后将标记设为1 chu.signal(); //唤醒输出线程 } finally { lock.unlock(); } } public void get() { lock.lock(); try { if(flag==0) //if flag is 0,the thread of printing wont print.waiting for setting. { try { chu.await(); //thread of print is waiting. } catch(InterruptedException e) { e.printStackTrace(); } } System.out.println(this.name+"....."+this.sex); flag=0; //输出后将标记设为0 jin.signal(); //唤醒设置线程 } finally { lock.unlock(); } } } class in implements Runnable { private Person p; in(Person p) { this.p=p; } public void run() { for(int i=0;i<100;i++) { if(i%2==0) p.set("ZhangSan","man"); else p.set("WangLi","woman"); } } } class out implements Runnable { private Person p; out(Person p) { this.p=p; } public void run() { for(int i=0;i<100;i++) { p.get(); } } } class ThreadDemo { public static void main(String[] args) { Person p=new Person(); new Thread(new in(p)).start(); new Thread(new out(p)).start(); } }