多线程编程

多线程编程思路

1、采用多线程操作资源类,满足高类聚,低耦合的思想。所有的操作封装成方法,在主线程中创建线程并直接调用其方法。

2、在资源类中编写供线程调用的方法步骤为:

  • 判断
    先判断,当前线程是否满足条件执行。并且注意避免虚假唤醒
while(!condition){
      condition.await();
}
  • 执行
    执行当前线程的逻辑代码
  • 唤醒其他线程
condition.signalAll();

题目

一个初始值为0的变量,两个线程交替对其加一减一,执行五次。



import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;

/**
 * 资源类,资源类里有对应的锁对象,在主线程中只需要调用其方法
 */
class Resource {
    private int num = 0;
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void increase() {
        lock.lock();
        try {
            while (num != 0) {
                condition.await();
            }
            num++;
            System.out.printf("%s\tnum = %d%n", Thread.currentThread().getName(), num);
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void decrease() {
        lock.lock();
        try {
            while (num == 0) {
                condition.await();
            }
            num--;
            System.out.printf("%s\tnum = %d%n", Thread.currentThread().getName(), num);
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

public class Main {

    public static void main(String[] args) {
        Resource resource = new Resource();
        new Thread(() -> {
            IntStream.range(0, 5).forEach(i -> {
                resource.increase();
            });
        }, "A").start();
        new Thread(() -> {
            IntStream.range(0, 5).forEach(i -> {
                resource.decrease();
            });
        }, "B").start();
    }
}

A num = 1
B num = 0
A num = 1
B num = 0
A num = 1
B num = 0
A num = 1
B num = 0
A num = 1
B num = 0

三个线程交替打印ABC

最好的方式是采用三个condition,使用signal方法实现精确唤醒,并使用状态值切换状态。推荐使用这种方式。


import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;

class Resource {
    private int num = 1;
    private Lock lock = new ReentrantLock();
    private Condition c1 = lock.newCondition();
    private Condition c2 = lock.newCondition();
    private Condition c3 = lock.newCondition();

    public void printA() {
        lock.lock();
        try {
            while (num != 1) {
                c1.await();
            }
            System.out.println("A");
            num = 2;
            c2.signal();//唤醒printB的线程
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printB() {
        lock.lock();
        try {
            while (num != 2) {
                c2.await();
            }
            System.out.println("B");
            num = 3;
            c3.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printC() {
        lock.lock();
        try {
            while (num != 3) {
                c3.await();
            }
            System.out.println("C");
            num = 1;
            c1.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Resource resource = new Resource();
        new Thread(()->{
            IntStream.range(0,10).forEach(i->{
                resource.printA();
            });
        }).start();new Thread(()->{
            IntStream.range(0,10).forEach(i->{
                resource.printB();
            });
        }).start();
        new Thread(() -> {
            IntStream.range(0, 10).forEach(i -> {
                resource.printC();
            });
        }).start();
    }
}

采用一个condition也可以,关键还是状态值的切换。


import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;

class Resource {
    private int num = 1;
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void printA() {
        lock.lock();
        try {
            while (num != 1) {
                condition.await();
            }
            System.out.println("A");
            num = 2;
            condition.signalAll();//唤醒printB的线程
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printB() {
        lock.lock();
        try {
            while (num != 2) {
                condition.await();
            }
            System.out.println("B");
            num = 3;
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printC() {
        lock.lock();
        try {
            while (num != 3) {
                condition.await();
            }
            System.out.println("C");
            num = 1;
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Resource resource = new Resource();
        new Thread(() -> {
            IntStream.range(0, 10).forEach(i -> {
                resource.printA();
            });
        }).start();
        new Thread(() -> {
            IntStream.range(0, 10).forEach(i -> {
                resource.printB();
            });
        }).start();
        new Thread(() -> {
            IntStream.range(0, 10).forEach(i -> {
                resource.printC();
            });
        }).start();
    }
}
posted @ 2020-07-28 18:45  刃牙  阅读(171)  评论(0编辑  收藏  举报