多线程编程简单例子学习(1)

一道线程题目引出的问题:
    1. 题目: 设计4个线程,其中两个线程每次对j增长1,另外两个线程对j每次减小1。写出程序。
    2. 实现:
       资源类:
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关键字。 测试

相关文章
相关标签/搜索