java Thread线程实例

来源:互联网 发布:java校招面试 编辑:程序博客网 时间:2024/05/22 03:34
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 ;}@Overridepublic 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;}@Overridepublic 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 0
原创粉丝点击