package com.lxh.Thread2; // 资源类 public class Resource { // 初始值 public int initValue = 0; }加1线程类:
package com.lxh.Thread2; // 加1操做 public class IncreaseThread implements Runnable { // 变量 public Resource res; // 构造方法 public IncreaseThread(Resource resource) { this.res = resource; } @Override public void run() { for(int i=0;i<5;i++){ synchronized (res) { this.res.initValue = res.initValue + 1; System.out.println(res+"***当前线程" + Thread.currentThread().getName() + ",加1以后initValue=" + res.initValue + "***"); } } } }减1线程类:
package com.lxh.Thread2; // 减1操做 public class ReduceThread implements Runnable { // 变量 public Resource res; // 构造方法 public ReduceThread(Resource resource) { this.res = resource; } @Override public void run() { for(int i=0;i<5;i++){ synchronized (res) { this.res.initValue = res.initValue - 1; System.out.println(res+"***当前线程" + Thread.currentThread().getName() + ",减1以后initValue=" + res.initValue + "***"); } } } }测试类:
package com.lxh.Thread2; public class Test { public static void main(String[] args) { Resource res = new Resource(); IncreaseThread it = new IncreaseThread(res); ReduceThread rt = new ReduceThread(res); Thread t1 = new Thread(it); Thread t2 = new Thread(it); Thread t3 = new Thread(rt); Thread t4 = new Thread(rt); t1.start(); t2.start(); t3.start(); t4.start(); } }3. 运行结果
小结: 这是一个简单的"生产者----消费者"应用。 (为何定一个资源类做为参数传递? 由于这样的话能够保证initValue值在4个线程中共享,若是只是定义一个int类型的变量则只能在相同的线程之间共享,好比同增或同减,不能在不一样线程之间共享,好比加1线程和减1线程之间进行共享。) java
4. 若是在测试类中设置线程优先级,相关程序以下: 安全
package com.lxh.Thread2; // 加1操做 public class IncreaseThread implements Runnable { // 变量 public Resource res; // 构造方法 public IncreaseThread(Resource resource) { this.res = resource; } @Override public void run() { for(int i=0;i<20;i++){ synchronized (res) { this.res.initValue = res.initValue + 1; System.out.println(res+"***当前线程" + Thread.currentThread().getName() + ",加1以后initValue=" + res.initValue + "***"); } } } }
package com.lxh.Thread2; // 减1操做 public class ReduceThread implements Runnable { // 变量 public Resource res; // 构造方法 public ReduceThread(Resource resource) { this.res = resource; } @Override public void run() { for(int i=0;i<15;i++){ synchronized (res) { this.res.initValue = res.initValue - 1; System.out.println(res+"***当前线程" + Thread.currentThread().getName() + ",减1以后initValue=" + res.initValue + "***"); } } } }
package com.lxh.Thread2; public class Test { public static void main(String[] args) { Resource res = new Resource(); IncreaseThread it = new IncreaseThread(res); ReduceThread rt = new ReduceThread(res); Thread t1 = new Thread(it); Thread t2 = new Thread(it); Thread t3 = new Thread(rt); Thread t4 = new Thread(rt); // 设置线程优先级 t1.setPriority(Thread.MIN_PRIORITY);// 优先级最低 t2.setPriority(Thread.MAX_PRIORITY);// 优先级最高 t3.setPriority(3); t4.setPriority(7); t1.start(); t2.start(); t3.start(); t4.start(); } }运行结果:
小结:线程的优先级是能够调节的,最高级为10(Thread.MAX_PRIORITY),最低级为1(Thread.MIN_PRIORITY),默认为Thread.NORM_PRIORITY,越大得到CPU资源的能力就越强,特别说明:线程执行的次数多的时候该规律才明显。 多线程
5. 为何须要加synchronized关键字?代码说明 ide
package com.lxh.Thread2; // 减1操做 public class ReduceThread implements Runnable { // 变量 public Resource res; // 构造方法 public ReduceThread(Resource resource) { this.res = resource; } @Override public void run() { System.out.println(res.initValue); for(int i=0;i<15;i++){ this.res.initValue = res.initValue - 1; System.out.println(res+"***当前线程" + Thread.currentThread().getName() + ",减1以后initValue=" + res.initValue + "***"); } } }
package com.lxh.Thread2; public class Test { public static void main(String[] args) { Resource res = new Resource(); IncreaseThread it = new IncreaseThread(res); ReduceThread rt = new ReduceThread(res); Thread t3 = new Thread(rt); Thread t4 = new Thread(rt); t3.start(); t4.start(); } }运行结果:
产生错误缘由:
Thread-3线程先获取CPU资源执行,输出res.initValue值(初始为0),刚执行到for循环里面,线程Thread-2就夺取了CPU资源,此时Thread-3在(this.res.initValue=res.initValue-1)到处于闲置状态(不能说是等待状态wait---等待状态须要唤醒notify),而后Thread-2就开始输出res.initValue值,而后,进入for循环,执行this.res.initValue = res.initValue-1;此时res.initValue=-1,就在此刻,Thread-3从新夺回CPU资源,执行this.res.initValue=res.initValue-1;此时res.initValue=-2,输出1这行代码,这个时候,Thread-2又从新夺回CPU资源,执行2这行代码。
这就很好揭示了多线程出现安全问题的缘由:多个线程在同时执行某多行代码的时候,一个线程只执行了多行代码的部分,其余线程就参与进来执行,形成共享数据错误。解决方案就是:在共享代码段加上synchronized关键字。 测试