Java的第一个坑,多线程入门

来源:互联网 发布:拜年视频制作软件 编辑:程序博客网 时间:2024/05/22 17:05

起因是一道笔试题:
http://edisonxu.org/2017/03/02/java-thread-communication.html#comments
(上面这篇文章中提到的关于volatile的答案似乎有问题)

几个坑的地方:
1. wait() 和notify() 一定是在synchronized()块中出现
 wait() 发生时会当前线程释放锁
 notify()发生时,会?
2. notify() 出现在wait() 之前则无效(和条件变量的区别)
3. Integer虽然可以调用wait(),notify(),但是由于赋新值时会改变对象,所以不能用在这里,要自己定义一个类似的东西

我的代码:

1,Ojbect,synchronized,wait,notify版

package mytest;public class ThreadTest {    static class ThreadNum{        public int i;        public ThreadNum(int value){            i=value;        }    }    private Object w1=new Object ();    private Object w2=new Object();    private Object o=new Object();    private ThreadNum cur=new ThreadNum(1);//must use self-define type    public Runnable newThreadOne() {        return new Runnable() {            public void run() {                try {                        for (int i = 0; i < 52; i=i+2) {                            synchronized (cur) {//must inside synchronized block                                if(cur.i==2)//从逻辑上来说,只有两个线程if应该没问题;但是有个叫Spurious wakeup 的东西要求这个地方一定要用while,然而懒得改了                                {                                    cur.wait();                                }                                System.out.print(i+1);                                System.out.print(i+2);                                cur.i=2;                                cur.notify();                            }                    }                } catch (InterruptedException e) {                    System.out.println("Oops...");                }            }        };    }    public Runnable newThreadTwo() {        return new Runnable() {            public void run() {                try {                    for (int i = 0; i < 26; i++) {                            synchronized (cur) {                                if(cur.i==1)                                {                                    cur.wait();                                }                                System.out.print((char)('a'+i));                                cur.i=1;                                cur.notify();                            }                    }                } catch (InterruptedException e) {                    System.out.println("Oops...");                }            }        };    }    public static void main(String args[]) throws InterruptedException {        /*        Object o=new Object();        synchronized (o) {            o.notify();            System.out.println("notified");            o.wait();            System.out.println("wait");        }*/        ThreadTest test = new ThreadTest();        Thread t1=new Thread(test.newThreadOne());        Thread t2=new Thread(test.newThreadTwo());        t1.start();        t2.start();    }}

2.condition,lock,unlock,await,signal版

java的signal函数似乎一定是要持有锁的线程调用,这点和C的pthread_cond_t 不同

package mytest;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class ConditionTest {    private Lock lock=new ReentrantLock(true);    private Condition condition1=lock.newCondition();    private Condition condition2=lock.newCondition();    private int thread_to_run=1;    public Runnable newThreadOne() {        return new Runnable() {            public void run() {                try {                        for (int i = 0; i < 52; i=i+2) {                            synchronized (lock) {                                while(thread_to_run!=1){                                    condition1.wait();                                }                                System.out.print(i+1);                                System.out.print(i+2);                                condition2.signal();                            }                    }                } catch (InterruptedException e) {                    System.out.println("Oops...");                }            }        };    }    public Runnable newThreadTwo() {        return new Runnable() {            public void run() {                try {                    for (int i = 0; i < 26; i++) {                            synchronized (lock) {                                while(thread_to_run!=2){                                    condition2.await();                                }                                System.out.print((char)('a'+i));                                condition1.signal();                            }                    }                } catch (InterruptedException e) {                    System.out.println("Oops...");                }            }        };    }    public static void main(String args[]) throws InterruptedException {        /*        Lock lock=new ReentrantLock(true);        Condition condition1=lock.newCondition();        condition1.signal();        System.out.println("signal");        lock.lock();        System.out.println("before wait");        condition1.await();        System.out.println("wait");        condition1.signal();        System.out.println("signal");        lock.unlock();        */        ThreadTest test = new ThreadTest();        Thread t1=new Thread(test.newThreadOne());        Thread t2=new Thread(test.newThreadTwo());        t1.start();        t2.start();        t1.join();        t2.join();    }}

3.信号量 semaphore,acquire,release

个人感觉信号量的版本最简单,因为这是一个关于顺序控制的问题,所以信号量会直接管理一个相关的计数器,不用像前面的程序那样需要自己控制另外一个变量

package mytest;import java.util.concurrent.Semaphore;public class SemaphoreTest {    static class ThreadNum{        public int i;        public ThreadNum(int value){            i=value;        }    }    private Semaphore w1=new Semaphore(1);    private Semaphore w2=new Semaphore(0);    public Runnable newThreadOne() {        return new Runnable() {            public void run() {                try {                    for (int i = 0; i < 52; i=i+2) {                        w1.acquire();                        System.out.print(i+1);                        System.out.print(i+2);                        w2.release();                    }                } catch (InterruptedException e) {                    System.out.println("Oops...");                }            }        };    }    public Runnable newThreadTwo() {        return new Runnable() {            public void run() {                try {                    for (int i = 0; i < 26; i++) {                        w2.acquire();                        System.out.print((char)('a'+i));                        w1.release();                    }                } catch (InterruptedException e) {                    System.out.println("Oops...");                }            }        };    }    public static void main(String args[]) throws InterruptedException {        ThreadTest test = new ThreadTest();        Thread t1=new Thread(test.newThreadOne());        Thread t2=new Thread(test.newThreadTwo());        t1.start();        t2.start();        t1.join();        t2.join();    }}

参考:
1.异常
http://blog.csdn.net/historyasamirror/article/details/6709693
2.条件变量
http://blog.csdn.net/woshixuye/article/details/28283289
3.

原创粉丝点击