java Thread线程实例

synchronized使用起来非常简单,有三种使用模式:

1. 作为修饰符加在方法声明上,synchronized修饰非静态方法时表示 锁住了调用该方法的堆对象,修饰静态方法时表示 锁住了这个类在方法区中的类对象(记住JAVA中everything is object)。

2.可以用synchronized直接构建代码块。

3.在使用Object.wait()使当前线程进入该Object的阻塞队列时,以及用Object.notify()或Object.notifyAll()唤醒该Object的阻塞队列中一个或所有线程时,必须在外层使用synchronized (Object),这是JAVA中线程同步的最常见做法。之所以在这里要强制使用synchronized代码块,是因为在JAVA语义中, wait有出让Object锁的语义,要想出让锁,前提是要先获得锁,所以要先用synchronized获得锁之后才能调用wait,notify原因类似,另外,我们知道操作系统信号量的增减都是原子性的,而Object.wait()和notify()不具有原子性语义,所以必须用synchronized保证线程安全。

另外,在使用synchronized时有三个原则:

a) sychronized的对象最好选择引用不会变化的对象(例如被标记为final,或初始化后永远不会变),原因显而易见的,虽然synchronized是在对象上加锁,但是它首先要通过引用来定位对象,如果引用会变化,可能带来意想不到的后果,对于需要synchronized不同对象的情况,建议的做法是为每个对象构建一个Object锁来synchronized(不建议对同一个引用反复赋值)。当然将synchronized作为修饰符修饰方法就不会有引用变化的问题,但是这种做法在方法体较大时容易违反第二个原则。

b) 尽可能把synchronized范围缩小,线程互斥是以牺牲并发度为代价的,这点大家都懂。

c) 尽量不要在 可变引用上wait()和notify()。


现在需要计算1+2+3+....+30000的和。请采用多线程完成此计算工作,要求如下:
主线程启动三个线程,分别给它们分派以下任务:

线程1:计算1+2+3+...+10000

线程2:计算10001+10002+...+20000

线程3:计算20001+20002+...+30000

等三个线程都完成工作之后,主线程汇总三个工作线程的计算结果,得到最终答案:

1 + 2 + 3 + .... + 30000 = 450015000


/**
 * 
 */
package test.SyncAdd;

/**       
 * @projectName:zhngdps 
 * @packageName: test.SyncAdd
 * @ClassName  : SyncAddTest
 * @createBy   :Test 
 * @createDate :2014-6-5 上午09:03:35   
 * @useFor     : 
 *    
 */
public class SyncAddTest {

	private int getAddCount(int begin,int end,String threadName)
	{
		 TestA test1 = new TestA(begin,end);
	     Thread th1 = new Thread(test1,threadName);
	     th1.start() ;
	     /*
	      * 对线程对象加锁  针对的是同一个类的多个对象的线程
	      * 使得多线程运行结果可以控制,synchronized用于保护共享数据
	      */
	     synchronized (th1) {
		    	try {
		    	   th1.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		  return test1.getSum() ;
		}
    }
	
	public static void main(String[] args) {
		SyncAddTest t = new SyncAddTest();
		int sum1 = t.getAddCount(0,10000,"th1");
		System.out.println(sum1);
		int sum2 = t.getAddCount(10001,20000,"th2") ;
		System.out.println(sum2);
		int sum3 = t.getAddCount(20001,30000,"th3") ;
		System.out.println(sum3);
		int sum = sum1 + sum2 + sum3 ;
		System.out.println(sum);

	}
};

class TestA implements Runnable
{
	private int begin ;
	private int end ;
	private int sum = 0;
	public TestA(int begin,int end)
	{
		this.begin = begin ;
		this.end = end ;
	}
	@Override
	public void run() {
		add();
		System.out.println(Thread.currentThread().getName());
	}
	
	private void add()      
	{
		for(int i=begin;i<=end;i++)
		{
			sum += i ;
		}
	}
	
	public int getSum()
	{
		return this.sum ;
	}
};


使用while true的方式进行阻塞主函数从而使线程继续执行直到线程执行完毕



class ThTest implements Runnable {

	private int start;

	private int end;

	private int sum = 0;

	private boolean isComplete = false;

	public boolean isComplete() {
		return isComplete;
	}

	public ThTest() {
		super();
	}

	public ThTest(int start, int end) {
		this.start = start;
		this.end = end;
	}

	public int getSum() {
		return this.sum;
	}

	@Override
	public void run() {
		synchronized (this) {
			for (int i = start; i <= end; i++) {
				sum += i;
			}
			isComplete = true;
		}
	}
public static void main(String[] args) {
		
		ThTest thTest01 = new ThTest(1, 50000);
		ThTest thTest02 = new ThTest(50001, 100000);

		Thread thread01 = new Thread(thTest01);
		Thread thread02 = new Thread(thTest02);
		
		ExecutorService threaPool = Executors.newCachedThreadPool();
		threaPool.execute(thread01);
		threaPool.execute(thread02);

		while (true) {
			System.out.print("");
			if (thTest01.isComplete() && thTest02.isComplete()) {
				break;
			}
		}

		System.out.println("总数为:" + (thTest01.getSum() + thTest02.getSum()));
		threaPool.shutdown();
	}
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值