Java之 线程(二)

提问

Thread和Runnable的区别?
sleep和yield的区别?

线程同步

什么是线程同步?

如下代码

public class Data {
    private int count = 0;

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

public class MyThreadRunnable implements Runnable {

    private Data data = new Data();

    @Override
    public void run() {
        int tmp = data.getCount();
        ++tmp;
        data.setCount(tmp);
        System.out.println(Thread.currentThread().getName() + "|" + data.getCount());
    }
}

执行方式为

MyThreadRunnable runnable = new MyThreadRunnable();
for (int i = 0; i < 5; i++) {
    Thread thread = new Thread(runnable);
    thread.start();
}

上面的打印结果为什么呢?

当然了这个只是一个简单的完全不耗时的操作,如果把执行代码块修改为

public class MyThreadRunnable implements Runnable {

    private Data data = new Data();

    @Override
    public void run() {
        int tmp = data.getCount();
        ++tmp;
        data.setCount(tmp);
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "|" + data.getCount());
    }
}

执行结果为

Thread-0|5
Thread-1|5
Thread-3|5
Thread-4|5
Thread-2|5

也就是说以上的代码执行有可能是无法预测的,需要增加一个同步操作来保证代码块的稳定。

synchronized

参考:synchronized-in-java

修改代码为

public class MyThreadRunnable implements Runnable {

    private Data data = new Data();

    @Override
    public synchronized void run() {
        int tmp = data.getCount();
        ++tmp;
        data.setCount(tmp);
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "|" + data.getCount());
    }
}

执行结果为:

Thread-0|1
Thread-4|2
Thread-3|3
Thread-2|4
Thread-1|5

wait,notify

  • wait()
    Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.
  • void wait(long timeout)
    Causes the current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object, or a specified amount of time has elapsed.
  • void wait(long timeout, int nanos)
    Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object, or some other thread interrupts the current thread, or a certain amount of real time has elapsed.
  • void notify()
    Wakes up a single thread that is waiting on this object's monitor.
  • void notifyAll()
    Wakes up all threads that are waiting on this object's monitor.

实体数据

public class Data {
    private int count = 15;

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

线程1

public class Thread1 extends Thread {

    private Data data;

    public Thread1(Data data) {
        super();
        this.data = data;
    }

    @Override
    public void run() {
        DataService service = new DataService();
        for (int i = 0; i < 100; i++) {
            service.add(data);
        }
    }
}

线程2

public class Thread2 extends Thread {

    private Data data;

    public Thread2(Data data) {
        super();
        this.data = data;
    }

    @Override
    public void run() {
        DataService service = new DataService();
        for (int i = 100; i > 0; i--) {
            service.del(data);
        }
    }
}

数据示例

public class DataService {

    private static final int MAX_COUNT = 10;
    private static final int MIN_COUNT = 1;

    public void add(Data data) {
        synchronized (data) {
            if (data.getCount() >= MAX_COUNT) {
                try {
                    System.out.println("count reach max");
                    data.wait();
                    System.out.println("count add wait finish");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return;
            }

            int count = data.getCount();
            ++count;
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            data.setCount(count);
            System.out.println("current add count = " + data.getCount());
            data.notifyAll();
        }
    }

    public void del(Data data) {
        synchronized (data) {
            if (data.getCount() <= MIN_COUNT) {
                try {
                    System.out.println("count reach min");
                    data.wait();
                    System.out.println("count del wait finish");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return;
            }

            int count = data.getCount();
            count--;
            data.setCount(count);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("current del count == " + data.getCount());
            data.notifyAll();
        }
    }
}

上面场景一般应用是什么?

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容