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

起因是一道笔试题:
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.

你可能感兴趣的:(Java)