Java多线程基础知识整理二
线程状态
* 新生状态:用new关键字和thread类或其子类建立一个线程对象后,该线程对象就处于新生状态,处于新生状态的
* 线程拥有自己的内存空间,通过调用start方法进入就绪状态
* 就绪状态:处于就绪状态的线程已经具备了运行条件,但还没有分配到cpu,处于线程就绪队列,等待系统为其分配cpu,
* 等待系统为其分配cpu,等待状态并不是执行状态,当系统选定一个等待执行的Thread对象后,他就会从等待执行状态
* 执行状态,系统挑选的动作称之为cpu调度,一旦获得cpu,线程就进入运行状态并自动调用自己的run方法;
* 运行状态: 在运行状态的线程执行自己run方法的代码,直到调用其他方法而终止,或等待某资源而阻塞或完成任务而死亡
* ,如果在给定的时间内没有执行结束,就会被系统给换下来回到等待执行状态;
* 阻塞状态:
* 处于运行状态的线程在某些情况下,如执行了sleep睡眠方法,或等待I/O设备等资源,将让出cpu并暂时停止自己的运行
* 进入阻塞状态,在阻塞状态的线程不能进入就绪队列,只有当引起阻塞的原因消除时,如睡眠时间已到,或等待的I/O设备空闲下来
* ,线程便转入就绪状态,重新到就绪队列中排队等待,被系统选中后从原来的位置开始继续运行
* 死亡状态:
* 死亡状态时线程生命周期中的最后一个阶段,线程死亡的原因有两个,一个是正常运行的状态完成了它的全部工作
* 另一个是线程被强制性的终止,如通过stop或destroy方法来终止一个线程(不推荐使用这两个方法,前者会产生异常,后者是强制终止
* ,不会释放锁)
停止线程:
* 1.自然终止:线程体常执行完毕;
* 外部干涉:
* 1.线程内中定义线程体中使用的标志;
* 2.线程体使用该标志;
* 3.提供对外的方法改变该标志
package Tread; public class Thread06 { public static void main(String[] args) { Study s = new Study(); new Thread(s).start(); for (int i = 0; i < 1000; i++) { if (i == 50) { s.setFlag(false); } System.out.println("main" + "-----------" + i); } } } class Study implements Runnable { private boolean flag = true; @Override public void run() { while (flag) { System.out.println("Thread stop....."); } } public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } }
阻塞线程(一)
1.join:合并线程,下图代码阻塞了main方法;
package Tread; public class JoinDemo implements Runnable { public static void main(String[] args) throws InterruptedException { JoinDemo j = new JoinDemo(); Thread t = new Thread(j); t.start(); for (int i = 0; i < 1000; i++) { if (50 == i) { t.join(); } System.out.println("main...." + i); } } @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("join...." + i); } } }
* 2.yield:暂停自己的线程,让出cpu的调度:静态方法,
package Tread; public class YieldDemo implements Runnable { public static void main(String[] args) throws InterruptedException { YieldDemo j = new YieldDemo(); Thread t = new Thread(j); t.start(); for (int i = 0; i < 1000; i++) { if (i % 20 == 0) { Thread.yield(); } System.out.println("main...." + i); } } @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("yiled" + "...." + i); } } }
, 3.sleep:线程休眠时不会释放锁 经常用于两种情况:与时间相关的:倒计时 模拟网络延时
package Tread; public class SleepDemo { public static void main(String[] args) throws InterruptedException { int num = 10; while (true) { Thread.sleep(1000); System.out.println(num--); if (num < 0) { break; } } } }
模拟倒计时
package Tread; import java.text.SimpleDateFormat; import java.util.Date; public class SleepDemo01 { public static void main(String[] args) throws InterruptedException { Date endtime = new Date(System.currentTimeMillis() + 10 * 1000); long end = endtime.getTime(); while (true) { Thread.sleep(1000); System.out.println(new SimpleDateFormat("mm:ss").format(endtime)); endtime = new Date(endtime.getTime() - 1000); if (end - 10000 > endtime.getTime()) { break; } } } }
模拟网络延时
public class Demo { public static void main(String[] args) { Web12306 wb = new Web12306(); Thread t1 = new Thread(wb, "黄牛"); Thread t2 = new Thread(wb, "黄牛2"); Thread t3 = new Thread(wb, "工程师"); t1.start(); t2.start(); t3.start(); } } class Web12306 implements Runnable { int num = 10; private boolean flag = true; @Override public void run() { while(true) { if (num <= 0) { break; } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "抢到了" + num-- + "票"); } }