CPU时间片java
上下文切换,切换的时候须要保持任务的状态, 以便后续接着任务的状态执行。比较消耗CPU 资源。安全
死锁问题多线程
能够经过jconsole 工具来进行检测:ide
饥饿和活锁问题很差检测工具
如下代码低优先级的线程仍是有可能大多数状况下获取CPU时间片的,只是几率上会变小。性能
public class Target implements Runnable { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + "..."); } } } public class Demo8 { public static void main(String[] args) { Thread t = new Thread(new Target()); Thread t1 = new Thread(new Target()); Thread t2 = new Thread(new Target()); Thread t3 = new Thread(new Target()); t.setPriority(Thread.MAX_PRIORITY); //不一样平台优先级值不同,建议使用常量 t2.setPriority(Thread.MIN_PRIORITY); t.start(); t2.start(); } }
如何尽可能避免饥饿问题:线程
写一个数值生成器:3d
单线程环境下:code
public class Sequence { private int value; public int getNext() { return value++; } public static void main(String[] args) { Sequence sequence = new Sequence(); while (true) { System.out.println(sequence.getNext()); } } }
多线程环境:对象
package thread; public class Sequence { private int value; public int getNext() { return value++; } public static void main(String[] args) { Sequence sequence = new Sequence(); new Thread(new Runnable() { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + " " + sequence.getNext()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + " " + sequence.getNext()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + " " + sequence.getNext()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } }
会有数据重复的问题,这就是线程安全性问题
线程是多个执行顺序流,value++ 至关于 value = value + 1, 是两步操做
从java字节码角度来看线程安全性问题:
可使用 javap -verbose Sequence.class 来看字节码文件
0: aload_0 1: dup 2: getfield #2 // Field value:I 5: dup_x1 6: iconst_1 7: iadd 8: putfield #2 // Field value:I 11: ireturn
类的实例化对象它是放在堆内存中,堆是线程所共享的区域
程序计数器是线程所独享的区域
Value 是线程共享的区域
如何解决上面代码的线程安全性问题:
package thread; public class Sequence { private int value; public synchronized int getNext() { return value++; } public static void main(String[] args) { Sequence sequence = new Sequence(); new Thread(new Runnable() { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + " " + sequence.getNext()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + " " + sequence.getNext()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + " " + sequence.getNext()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } }
在 getNext() 方法前加了synchronized关键字,让方法变成同步方法就不会再有重复的数据
Synchronized 至关于一个门加了一把锁,当一个线程执行的时候,就获取了这把锁,而后把门锁上,其余线程来的时候就要在外面等待,等执行完毕后把锁释放,其余线程才能进来。就会致使同一时刻只会有一个线程执行该段代码。
本文主要介绍了线程的性能问题,死锁问题以及如何使用jconsole 查看线程是否发生死锁,线程的饥饿与公平,线程安全性问题:从字节码角度来分析线程安全性问题、如何解决线程安全的问题以及在什么状况下会出现线程安全性问题。
欢迎扫码关注,第一时间收到最新文章推送
个人博客即将同步至腾讯云+社区,邀请你们一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=14jki2ulsej09