阿里云虚拟主机建站教程,关于门户网站改版建设报告,深圳科源建设集团有限公司网站,建设工程合同司法解释目录 一、线程的状态
二、线程安全 一、线程的状态
1.NEW Thread#xff1a;对象创建好了#xff0c;但是还没有调用 start 方法在系统中创建线程。
2.TERMINATED#xff1a; Thread 对象仍然存在,但是系统内部的线程已经执行完毕了。
3.RUNNABLE#xff1a; 就绪状态对象创建好了但是还没有调用 start 方法在系统中创建线程。
2.TERMINATED Thread 对象仍然存在,但是系统内部的线程已经执行完毕了。
3.RUNNABLE 就绪状态表示这个线程正在 cpu 上执行,或者准备就绪随时可以去 pu 上执行。
4.TIMED WAITING 指定时间的阻塞.就在到达一定时间之后自动解除阻塞使用 sleep 会进入这个状态 使用带有超时时间的join也会。
5.WAITING 不带时间的阻塞(死等)必须要满足一定的条件,才会解除阻塞join 或者 wait 都会进入 WAITING。
6.BLOCKED 由于锁竞争,引起的阻塞.(后面线程安全的时候具体介绍)
这六种状态在生命周期的大概位置如图 用代码形式测试 NEW 、RUNNABLE、TERMINATED 状态 代码 public class ThreadDemo3 {private static int count 0;public static void main(String[] args) throws InterruptedException {Thread t new Thread(() - {for (int i 0; i 5000; i) {count;}System.out.println(count: count);});//t线程开始前System.out.println(t线程开始前: t.getState());t.start();//t线程执行中System.out.println(t线程执行中: t.getState());//t线程结束后t.join();System.out.println(t线程结束后: t.getState());}
} 执行效果 学习这些状态最大的作用就是调试多线程代码bug的时候给我们提供重要的参考依据当某个程序卡住了也就是意味着一些关键的线程阻塞了我们就可以观察线程的状态分享出一些原因。 注意一个线程只能start一次也就是说只有是NEW状态的线程才能start。 二、线程安全
线程安全某个代码不管它是单个线程执行还是多个线程执行都不会产生bug这个情况就成为“线程安全”。
线程不安全某个代码它单个线程执行不会产生bug但是多个线程执行就会产生bug这个情况就成为 “线程不安全”或者 “存在线程安全问题”。
举个线程不安全例子现在我们想计算一个变量的自增次数它循环了100000次用两个线程去计算各自计算循环50000次的次数。 代码 public class ThreadDemo4 {private static int count 0;public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {for (int i 1; i 50000; i) {count;}});Thread t2 new Thread(() - {for (int i 50000; i 100000; i) {count;}});t1.start();t2.start();t1.join();t2.join();System.out.println(count: count);}
}我们知道从1到10_0000肯定是自增了10_0000次但是我们看看输出结果如何 答案却不是10_0000是50000多次这是为何呢原因就是多线程代码它们是并发执行的。 这个count是由cpu的三个指令构成的 1load 从内存中读取数据到cpu的寄存器中。 2add 把寄存器中的值 1。 3save 把寄存器中的值写回到内存中。 因为上面两个线程是并发执行的那么 t1 和 t2 线程的执行顺序就是无序的他们可能同时读取数据自增完再1下面用图示他们的一些可能性。 暂时就画这么多因为线程并发的执行结果个数是无数的并不是简单的排列组合就能穷举出来因为并发的原因可能 t1 线程它执行了两次才执行一次 t2 线程也可能更多或者 t2 执行的次数更多t1 线程只执行一次。就又要排列组合了这些情况都是有可能的。 这时t1 和 t2自增的时候就可能拿的是同一个值这两线程的其中一个自增后没放回内存中另一个线程就又拿了这肯定是不符合我们预期的。 所以我们从上面的可能情况找符合我们预期的效果就只有这两个了如图 那么这种情况也就是串行化执行执行完 t1再执行t2或者两个顺序相反。 代码 public class ThreadDemo4 {private static int count 0;public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {for (int i 1; i 50000; i) {count;}});Thread t2 new Thread(() - {try {t1.join();} catch (InterruptedException e) {throw new RuntimeException(e);}for (int i 50000; i 100000; i) {count;}});t1.start();t2.start();t2.join();System.out.println(count: count);}
} 执行效果 但这样就没必要使用多线程了因为串行化一个线程就能搞定了使用多线程也没太大意义。