一、线程可以暂停意味着可以恢复
暂停用suspend(),resume()恢复线程。
package com.it.po.thread03; public class MyThread01 extends Thread { private long i=0; public long getI() { return i; } public void setI(long i) { this.i = i; } @Override public void run() { while (true){ i++; } } }
package com.it.po.thread03; import com.it.po.thread02.MyThread02; import javax.swing.*; public class Run01 { public static void main(String[] args){ try { MyThread01 my = new MyThread01(); my.start(); Thread.sleep(500); my.suspend();//暂停 System.out.println("第一次获取i= "+my.getI()+" 时间点:"+System.currentTimeMillis()); Thread.sleep(500); System.out.println("暂停后获取i= "+my.getI()+" 时间点:"+System.currentTimeMillis()); my.resume();//恢复 Thread.sleep(500); my.suspend();//再次暂停 System.out.println("恢复暂停后获取i= "+my.getI()+" 时间点:"+System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } } }

线程停止状态

(一)、suspend(),resume()方法的缺点-------独占
使用这两个方法,如果使用不当,极容易造成公共的同步对象的独占,使得其他线程
无法访问公共同步对象。
package com.it.po.thread03; public class SynchronizedObject { synchronized public void printString(){ System.out.println("线程 "+Thread.currentThread().getName()+" 进入printString方法..."); if("a".equals(Thread.currentThread().getName())){ System.out.println("a线程永远暂停了..."); Thread.currentThread().suspend(); } System.out.println("线程 "+Thread.currentThread().getName()+" 从printString方法出去..."); } }
package com.it.po.thread03; public class SysObjRun { public static void main(String[] args){ try { SynchronizedObject object = new SynchronizedObject(); //线程a Thread t1 = new Thread() { @Override public void run() { super.run(); object.printString(); } }; t1.setName("a"); t1.start(); Thread.sleep(1000); //线程b Thread t2 = new Thread() { @Override public void run() { super.run(); object.printString(); } }; t2.setName("b"); t2.start(); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }


暂停在这里,b线程永远进不去
变式1 去掉 synchronized
package com.it.po.thread03; public class SynchronizedObject { public void printString(){ System.out.println("线程 "+Thread.currentThread().getName()+" 进入printString方法..."); if("a".equals(Thread.currentThread().getName())){ System.out.println("a线程永远暂停了..."); Thread.currentThread().suspend(); } System.out.println("线程 "+Thread.currentThread().getName()+" 从printString方法出去..."); } }
线程 a 进入printString方法...
a线程永远暂停了...
线程 b 进入printString方法...
线程 b 从printString方法出去...
a线程一直停着。
(二)、第二种独占锁
package com.it.po.thread03; public class MyThread02 extends Thread { private long i=0; @Override public void run() { while (true){ i++; System.out.println("i= "+i); } } }
package com.it.po.thread03; public class Run02 { public static void main(String[] args){ try { MyThread02 my = new MyThread02(); my.start(); Thread.sleep(300); my.suspend(); System.out.println("main end。。。"); } catch (InterruptedException e) { e.printStackTrace(); } } }


分析:
当程序运行到println()方法内部时,同步锁未被释放,导致println()一直处于暂停状态

虽然suspend()作废了,但是研究它是有意义的。
(三)、suspend和resume方法的缺点----不同步
使用这两个方法,很容易出现因为行程暂停而数据不同步的情况。
package com.it.po.thread03; public class MyObject { private String username="1"; private String password="11"; public void setValue(String u,String p){ this.username=u; if("a".equals(Thread.currentThread().getName())){ System.out.println("a线程暂停了。。。"); Thread.currentThread().suspend(); } this.password=p; } public void printUsernameAndPassword(){ System.out.println("用户:"+username+" 密码 "+password); } }
package com.it.po.thread03; public class MyObjRun { public static void main(String[] args){ try { MyObject my = new MyObject(); //线程a Thread t1 = new Thread() { @Override public void run() { super.run(); my.setValue("a","aa"); } }; t1.setName("a"); t1.start(); Thread.sleep(1000); //线程b Thread t2 = new Thread() { @Override public void run() { super.run(); my.printUsernameAndPassword(); } }; t2.setName("b"); t2.start(); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }


二、yield方法
该方法的作用是放弃当前CPU资源,将它让给其他的任务去占用CPU时间,但是放弃的时间不确定
可能刚刚放弃,又马上获得CPU时间片
package com.it.po.thread03; public class MyThread03 extends Thread { @Override public void run() { long begin = System.currentTimeMillis(); int count=0; for(int i=0;i<5000000;i++){ // Thread.yield(); count=count+(i+1); } long end = System.currentTimeMillis(); System.out.println("用时: "+(end-begin)); } }
package com.it.po.thread03; public class Run03 { public static void main(String[] args){ MyThread03 my = new MyThread03(); my.start(); } }
用时: 9
去掉注释符号再次执行
用时: 3596
注意:这个3596时间是不确定的,可以多执行几次对比
三、线程的优先级
操作系统中线程可以划分优先级,优先级较高的线程得到CPU资源较多,也就是CPU优先执行,
优先级比较高的线程对象中的任务。
设置优先级有助于帮助 “线程规划器”确定下一次选择哪一个线程来优先执行。
设置线程的优先级用setPriority()方法。
此方法源码如下
/** * Changes the priority of this thread. * <p> * First the <code>checkAccess</code> method of this thread is called * with no arguments. This may result in throwing a * <code>SecurityException</code>. * <p> * Otherwise, the priority of this thread is set to the smaller of * the specified <code>newPriority</code> and the maximum permitted * priority of the thread's thread group. * * @param newPriority priority to set this thread to * @exception IllegalArgumentException If the priority is not in the * range <code>MIN_PRIORITY</code> to * <code>MAX_PRIORITY</code>. * @exception SecurityException if the current thread cannot modify * this thread. * @see #getPriority * @see #checkAccess() * @see #getThreadGroup() * @see #MAX_PRIORITY * @see #MIN_PRIORITY * @see ThreadGroup#getMaxPriority() */ public final void setPriority(int newPriority) { ThreadGroup g; checkAccess(); if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) { throw new IllegalArgumentException(); } if((g = getThreadGroup()) != null) { if (newPriority > g.getMaxPriority()) { newPriority = g.getMaxPriority(); } setPriority0(priority = newPriority); } }
线程优先级分为1~10级,小于1或是大于10则jdk抛出异常
JDK使用3个常量来预置定义优先级的值。
/** * The minimum priority that a thread can have. */ public final static int MIN_PRIORITY = 1; /** * The default priority that is assigned to a thread. */ public final static int NORM_PRIORITY = 5; /** * The maximum priority that a thread can have. */ public final static int MAX_PRIORITY = 10;
(一)、优先级具有继承特性
优先级具有继承性,比如A线程启动B线程,则B线程和A线程的优先级 一样
package com.it.po.thread03; public class MyThread04_1 extends Thread { @Override public void run() { System.out.println("MyThread04_1: priority= "+this.getPriority()); new MyThread04_2().start(); } }
package com.it.po.thread03; public class MyThread04_2 extends Thread { @Override public void run() { System.out.println("MyThread04_2:priority= "+this.
package com.it.po.thread03; public class Run04 { public static void main(String[] args){ System.out.println("main1 priority= "+Thread.currentThread().getPriority()); //Thread.currentThread().setPriority(8); System.out.println("main2 priority= "+Thread.currentThread().getPriority()); MyThread04_1 my = new MyThread04_1(); my.start(); } }
getPriority());
}
}
main1 priority= 5 main2 priority= 5 MyThread04_1: priority= 5 MyThread04_2:priority= 5
放开注释
main1 priority= 5 main2 priority= 8 MyThread04_1: priority= 8 MyThread04_2:priority= 8
(二)、优先级具有规则性
下面看优先级设置后带来的效果
package com.it.po.thread03; import java.util.Random; public class MyThread05_1 extends Thread { @Override public void run() { long begin = System.currentTimeMillis(); long addResult=0; for(int j=0;j<100;j++){ for(int i=0;i<5000;i++){ Random random = new Random(); random.nextInt(); addResult=addResult+i; } } long end = System.currentTimeMillis(); System.out.println("**********线程1用时 time= "+(end-begin)+" 毫秒"); } }
package com.it.po.thread03; import java.util.Random; public class MyThread05_2 extends Thread { @Override public void run() { long begin = System.currentTimeMillis(); long addResult=0; for(int j=0;j<100;j++){ for(int i=0;i<5000;i++){ Random random = new Random(); random.nextInt(); addResult=addResult+i; } } long end = System.currentTimeMillis(); System.out.println("**********线程2用时 time= "+(end-begin)+" 毫秒"); } }
package com.it.po.thread03; import java.util.Random; public class Run05 { public static void main(String[] args){ for(int i=0;i<5;i++) { MyThread05_1 my1 = new MyThread05_1(); my1.setPriority(10); my1.start(); MyThread05_2 my2 = new MyThread05_2(); my2.setPriority(1); my2.start(); } } }
**********线程1用时 time= 793 毫秒 **********线程1用时 time= 1056 毫秒 **********线程2用时 time= 936 毫秒 **********线程1用时 time= 1119 毫秒 **********线程1用时 time= 1288 毫秒 **********线程1用时 time= 1486 毫秒 **********线程2用时 time= 1581 毫秒 **********线程2用时 time= 1712 毫秒 **********线程2用时 time= 1919 毫秒 **********线程2用时 time= 1614 毫秒
优先级高的总是大部分先执行,但是不代表优先级高的先全部执行完。
CPU尽量将优先级高的线程先执行。
(三)、优先级具有随机性
其实优先级高的不一定先执行。优先级是具有随机性的。
package com.it.po.thread03; import java.util.Random; public class MyThread06_1 extends Thread { @Override public void run() { long begin = System.currentTimeMillis(); for(int i=0;i<2000;i++){ Random random = new Random(); random.nextInt(); } long end = System.currentTimeMillis(); System.out.println("**********线程1用时 time= "+(end-begin)+" 毫秒"); } }
package com.it.po.thread03; import java.util.Random; public class MyThread06_2 extends Thread { @Override public void run() { long begin = System.currentTimeMillis(); for(int i=0;i<2000;i++){ Random random = new Random(); random.nextInt(); } long end = System.currentTimeMillis(); System.out.println("**********线程2用时 time= "+(end-begin)+" 毫秒"); } }
package com.it.po.thread03; public class Run06 { public static void main(String[] args){ for(int i=0;i<5;i++) { MyThread06_1 my1 = new MyThread06_1(); my1.setPriority(5); my1.start(); MyThread06_2 my2 = new MyThread06_2(); my2.setPriority(6); my2.start(); } } }
**********线程2用时 time= 0 毫秒 **********线程1用时 time= 2 毫秒
**********线程1用时 time= 1 毫秒 **********线程2用时 time= 0 毫秒
**********线程2用时 time= 1 毫秒 **********线程2用时 time= 0 毫秒
**********线程2用时 time= 13 毫秒 **********线程1用时 time= 11 毫秒
**********线程1用时 time= 16 毫秒 **********线程1用时 time= 0 毫秒
优先级与打印的顺序无关
(四)、谁算的快
package com.it.po.thread03; public class ThreadA extends Thread{ private int count=0; public int getCount() { return count; } @Override public void run() { super.run(); while (true){ count++; } } }
package com.it.po.thread03; public class ThreadB extends Thread{ private int count=0; public int getCount() { return count; } @Override public void run() { super.run(); while (true){ count++; } } }
package com.it.po.thread03; public class RunAB { public static void main(String[] args){ try { ThreadA a = new ThreadA(); a.setPriority(Thread.NORM_PRIORITY-2);//优先级3 a.start(); ThreadB b = new ThreadB(); b.setPriority(Thread.NORM_PRIORITY+2);//优先级7 b.start(); Thread.sleep(6000); a.stop(); b.stop(); System.out.println("timeA= "+a.getCount()); System.out.println("timeB= "+b.getCount()); } catch (InterruptedException e) { e.printStackTrace(); } } }
timeA= 1452546210 timeB= 1473208109
优先级一样的话
package com.it.po.thread03; public class RunAB { public static void main(String[] args){ try { ThreadA a = new ThreadA(); a.setPriority(Thread.NORM_PRIORITY);//优先级5 a.start(); ThreadB b = new ThreadB(); b.setPriority(Thread.NORM_PRIORITY);//优先级5 b.start(); Thread.sleep(6000); a.stop(); b.stop(); System.out.println("timeA= "+a.getCount()); System.out.println("timeB= "+b.getCount()); } catch (InterruptedException e) { e.printStackTrace(); } } }
timeA= 1498458754 timeB= 1499677846
四、守护线程
java有两种线程,一种是用户线程,另一种是守护线程
守护线程:
是一种特殊线程,含有陪伴的含义,当进程中不含守护线程了,则守护线程自动销毁。
典型的守护线程就是垃圾回收线程。任何一个守护线程都是JVM中的所有非守护线程的保姆,
只要当前JVM中存在非守护线程,且没有结束,守护线程就要工作,只有当JVM中最后一个非守护线程结束了
守护线程随着JVM一同结束,守护线程的作用就是为其他线程提供便利。
package com.it.po.thread03; public class MyThread07 extends Thread { private long i=0; @Override public void run() { while (true){ try { i++; System.out.println("i= "+i); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
package com.it.po.thread03; public class Run07 { public static void main(String[] args){ try { MyThread07 my = new MyThread07(); my.setDaemon(true);//设置为守护线程 my.start(); Thread.sleep(6000); System.out.println("my是守护线程 ,main执行到此,my线程将也结束。。。"); } catch (InterruptedException e) { e.printStackTrace(); } } }

浙公网安备 33010602011771号