一、wait和sleep区别?
1.wait可以指定也可以不指定。sleep必须指定时间。
2.在同步中时,对cpu的执行权和锁的处理不同。它们都能将线程处于冻结状态。
wait:释放执行权,释放锁。
sleep:释放执行权,不释放锁。
二、线程的结束
1.调用该线程的stop()方法结束线程。容易导致不可预知的错误不推荐。
2.run()方法执行结束,线程正常结束,常用标志位来结束线程。
例:用标志位来结束线程
package com.test2; class StopThread1 implements Runnable { private boolean flag=true; public void run() { while(flag) { System.out.println(Thread.currentThread().getName()+"...."); } } public void setFlag() { flag=false; } } public class Demo2 { public static void main(String[] args) { StopThread1 st=new StopThread1(); Thread t1=new Thread (st); t1.start(); int num=1; for(;;) { if(++num==10) { st.setFlag(); break; } System.out.println("main"+num); } System.out.println("over"); } }
问题:在上面代码加入wait()方法后,将线程处于冻结状态无法读取标记。如何结束呢?—可以使用interrupt
package com.test2; class StopThread1 implements Runnable { private boolean flag=true; public synchronized void run() { while(flag) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"...."); } } public void setFlag() { flag=false; } } public class Demo2 { public static void main(String[] args) { StopThread1 st=new StopThread1(); Thread t1=new Thread (st); t1.start(); int num=1; for(;;) { if(++num==10) { st.setFlag(); break; } System.out.println("main"+num); } System.out.println("over"); } }
3.使用interrupt来中断线程(其实是清除wait sleep中断状态)。
* Interrupt //可以将线程从冻结状态强制恢复到运行状态中来,让cpu具备执行资格。
* 但是强制动作会发生中断异常,记得要处理,(可在异常处理中设置标志),那么再次判断标志后就可以结束线程。
package com.test2; class StopThread1 implements Runnable { private boolean flag=true; public synchronized void run() { while(flag) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"...."); } } public void setFlag() { flag=false; } } public class Demo2 { public static void main(String[] args) { StopThread1 st=new StopThread1(); Thread t1=new Thread (st); Thread t2=new Thread (st); t1.start(); t2.start(); int num=1; for(;;) { if(++num==10) { st.setFlag(); t1.interrupt(); break; } System.out.println("main"+num); } System.out.println("over"); } }
三、守护线程setDaemon()、join线程
1.当前台线程结束后,后台线程就会自动结束。
记住要在线程开启之前设置守护线程,不然会报错。
package com.test2; class StopThread1 implements Runnable { private boolean flag=true; public synchronized void run() { while(flag) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); flag=false; } System.out.println(Thread.currentThread().getName()+"...."); } } } public class Demo2 { public static void main(String[] args) { StopThread1 st=new StopThread1(); Thread t1=new Thread (st); Thread t2=new Thread (st); t1.start(); t2.setDaemon(true); t2.start(); int num=1; for(;;) { if(++num==10) { t1.interrupt(); break; } System.out.println("main"+num); } System.out.println("over"); } }
2.join方法让一个现场当代另一个线程完成的方法——join()方法。当在某个程序执行流中调用其他线程的join方法时,
调用线程将被阻塞,知道join方法加入的join线程执行完为止。join方法适合将打的问题划分为小的问题,每个小问题分配
一个线程,小线程执行完后再调用主线程进一步处理。
3.toString()方法,返回该线程的字符串表现形式,包括线程名称、优先级和线程组。
4.yield()暂停当前正在执行的线程对象,并执行其他线程,注意它只是释放执行权,再次和其他线程抢夺线程。
典型面试题:
new Thread(new Runnable() { //用匿名内部类创建线程 @Override public void run() //父类线程任务 { System.out.println("runnable run"); } }) {public void run() //子类方法 { System.out.println("subThread run"); //子类方法将父类方法覆盖 所以输出subThread run
} }.start();