线程间的协作

疑问

  • 为什么wait()要放到while循环里?
    外界的某种变量条件发生改变,当前线程被唤醒,但此时被唤醒有可能不是满足我当前线程条件而进行之后的逻辑。假设有这样一个情景,当前线程被处于阻塞,某一线程调用notifyall(),当时可能满足条件变量,但是其中被唤醒的另一个线程又改变了条件变量,然而等到当前线程被唤醒,但并不满足逻辑所需,所以此时需要再次对wait()条件进行判断,是否此时满足逻辑,否则继续wait()。

同步队列的方式

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

/**
 * BlockingQueue 
 * 一台机器有3个任务,1、制作吐司 2、上黄油 3、 途果酱
 * @author liqiushi
 *
 */

/**
 * 吐司
 * 
 * @author liqiushi
 * 
 */
class Toast{
    public enum Status {
        DRY, BUTTERED, JAMMED
    }

    private final int id;
    private Status status = Status.DRY;

    public Toast(int id) {
        this.id = id;
    }

    public Status getStatus() {
        return status;
    }

    public void butter() {
        status = Status.BUTTERED;
    }

    public void jam() {
        status = Status.JAMMED;
    }

    public int getId() {
        return id;
    }

    public String toString() {
        return "toast " + id + ":" + status;
    }
}


 class ToastBlockQueue extends LinkedBlockingDeque<Toast> { }

/**
 * 制作吐司工
 * 
 * @author liqiushi
 * 
 */
class Toaster implements Runnable {

    private ToastBlockQueue toastBlockQueue;
    private int count = 0;
    public Toaster(ToastBlockQueue toastBlockQueue){
        this.toastBlockQueue = toastBlockQueue;
    }
    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                Toast toast = new Toast(count++);
                System.out.println(toast);
                toastBlockQueue.put(toast);
            }
        } catch (Exception e) {
            System.out.println("Toaster interrupted");
        }
        System.out.println("Toaster off");
    }
}

/**
 * 黄油线程
 * 
 * @author liqiushi
 * 
 */
class Butter implements Runnable {
    private ToastBlockQueue toastBlockQueue;
    private ToastBlockQueue butteredQueue;

    public Butter(ToastBlockQueue toastBlockQueue, ToastBlockQueue butteredQueue) {
        this.toastBlockQueue = toastBlockQueue;
        this.butteredQueue = butteredQueue;
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                Toast toast = toastBlockQueue.take();
                toast.butter();
                System.out.println(toast);
                butteredQueue.put(toast);
            }
        } catch (Exception e) {
            System.out.println("Butter interrupted");
        }
        System.out.println("Butter off");
    }
}

class Jamer implements Runnable {
    private ToastBlockQueue butteredQueue;
    private ToastBlockQueue jamedQueue;

    public Jamer(ToastBlockQueue butteredQueue, ToastBlockQueue jamedQueue) {
        this.butteredQueue = butteredQueue;
        this.jamedQueue = jamedQueue;
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                Toast toast = butteredQueue.take();
                toast.jam();
                System.out.println(toast);
                jamedQueue.put(toast);
            }
        } catch (Exception e) {
            System.out.println("Jamer interrupted");
        }
        System.out.println("Jamer off");
    }
}

class Eater implements Runnable {
    private ToastBlockQueue jamedQueue;
    private int id = 0;
    public Eater(ToastBlockQueue jamedQueue) {
        this.jamedQueue = jamedQueue;
    }
    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                Toast toast = jamedQueue.take();
                if (toast.getId() != id++|| toast.getStatus() != Toast.Status.JAMMED) {
                    System.out.println("err");
                    System.exit(1);
                } else {
                    System.out.println("eat!");
                }
            }
        } catch (Exception e) {
            System.out.println("eater interrupted");
        }
        System.out.println("eater off");
    }
}

/**
 * test
 * @author liqiushi
 *
 */
public class BlockQueue {
    public static void main(String[] args) throws InterruptedException {
        ToastBlockQueue dryQueue = new ToastBlockQueue();
        ToastBlockQueue butterQueue = new ToastBlockQueue();
        ToastBlockQueue jamQueue = new ToastBlockQueue();
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(new Toaster(dryQueue));
        executorService.execute(new Butter(dryQueue, butterQueue));
        executorService.execute(new Jamer(butterQueue, jamQueue));
        TimeUnit.SECONDS.sleep(2);
        executorService.shutdownNow();
    }


            }

下面是java编程思想后面的一道练习

package ThreadCollaboration;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

class Toast {
    public enum Status {
        DRY, BUTTERED, JAMMED, READY {
            public String toString() {
                return BUTTERED.toString() + " & " + JAMMED.toString();
            }
        }
    }

    private Status status = Status.DRY;
    private final int id;

    public Toast(int idn) {
        id = idn;
    }

    public void butter() {
        status = (status == Status.DRY) ? Status.BUTTERED : Status.READY;
    }

    public void jam() {
        status = (status == Status.DRY) ? Status.JAMMED : Status.READY;
    }

    public Status getStatus() {
        return status;
    }

    public int getId() {
        return id;
    }

    public String toString() {
        return "Toast " + id + ": " + status;
    }
}

class ToastQueue extends LinkedBlockingQueue<Toast> {
}

class Toaster implements Runnable {
    private ToastQueue toastQueue;
    private int count;
    private Random rand = new Random(47);

    public Toaster(ToastQueue tq) {
        toastQueue = tq;
    }

    public void run() {
        try {
            while (!Thread.interrupted()) {
                TimeUnit.MILLISECONDS.sleep(100 + rand.nextInt(500));
                // Make toast
                Toast t = new Toast(count++);
                System.out.println(t);
                // Insert into queue
                toastQueue.put(t);
            }
        } catch (InterruptedException e) {
            System.out.println("Toaster interrupted");
        }
        System.out.println("Toaster off");
    }
}

// Apply butter to toast:
class Butterer implements Runnable {
    private ToastQueue inQueue, butteredQueue;

    public Butterer(ToastQueue in, ToastQueue buttered) {
        inQueue = in;
        butteredQueue = buttered;
    }

    public void run() {
        try {
            while (!Thread.interrupted()) {
                // Blocks until next piece of toast is available:
                Toast t = inQueue.take();
                t.butter();
                System.out.println(t);
                butteredQueue.put(t);
            }
        } catch (InterruptedException e) {
            System.out.println("Butterer interrupted");
        }
        System.out.println("Butterer off");
    }
}

// Apply jam to toast:
class Jammer implements Runnable {
    private ToastQueue inQueue, jammedQueue;

    public Jammer(ToastQueue in, ToastQueue jammed) {
        inQueue = in;
        jammedQueue = jammed;
    }

    public void run() {
        try {
            while (!Thread.interrupted()) {
                // Blocks until next piece of toast is available:
                Toast t = inQueue.take();
                t.jam();
                System.out.println(t);
                jammedQueue.put(t);
            }
        } catch (InterruptedException e) {
            System.out.println("Jammer interrupted");
        }
        System.out.println("Jammer off");
    }
}

// Consume the toast:
class Eater implements Runnable {
    private ToastQueue finishedQueue;

    public Eater(ToastQueue finished) {
        finishedQueue = finished;
    }

    public void run() {
        try {
            while (!Thread.interrupted()) {
                // Blocks until next piece of toast is available:
                Toast t = finishedQueue.take();
                // Verify that all pieces are ready for consumption:
                if (t.getStatus() != Toast.Status.READY) {
                    System.out.println(">>>> Error: " + t);
                    System.exit(1);
                } else
                    System.out.println("Chomp! " + t);
            }
        } catch (InterruptedException e) {
            System.out.println("Eater interrupted");
        }
        System.out.println("Eater off");
    }
}

// Outputs alternate inputs on alternate channels:
// 将dry分开成两个工作,一个黄油,一个酱
class Alternator implements Runnable {
    private ToastQueue inQueue, out1Queue, out2Queue;
    private boolean outTo2; // control alternation

    public Alternator(ToastQueue in, ToastQueue out1, ToastQueue out2) {
        inQueue = in;
        out1Queue = out1;
        out2Queue = out2;
    }

    public void run() {
        try {
            while (!Thread.interrupted()) {
                // Blocks until next piece of toast is available:
                Toast t = inQueue.take();
                if (!outTo2)
                    out1Queue.put(t);
                else
                    out2Queue.put(t);
                outTo2 = !outTo2; // change state for next time
            }
        } catch (InterruptedException e) {
            System.out.println("Alternator interrupted");
        }
        System.out.println("Alternator off");
    }
}

// Accepts toasts on either channel, and relays them on to
// a "single" successor
// 合并两个工作,如果是黄油就进行涂酱,反之,(异步)如果是ready就进入完成队列
class Merger implements Runnable {
    private ToastQueue in1Queue, in2Queue, toBeButteredQueue, toBeJammedQueue,
            finishedQueue;

    public Merger(ToastQueue in1, ToastQueue in2, ToastQueue toBeButtered,
            ToastQueue toBeJammed, ToastQueue finished) {
        in1Queue = in1;
        in2Queue = in2;
        toBeButteredQueue = toBeButtered;
        toBeJammedQueue = toBeJammed;
        finishedQueue = finished;
    }

    public void run() {
        try {
            while (!Thread.interrupted()) {
                // Blocks until next piece of toast is available:
                Toast t = null;
                // 数据既可以来自黄油队列,也可以来自酱队列
                // 所以不用无限期的等待
                while (t == null) {
                    t = in1Queue.poll(50, TimeUnit.MILLISECONDS);
                    if (t != null)
                        break;
                    t = in2Queue.poll(50, TimeUnit.MILLISECONDS);
                }
                // Relay toast onto the proper queue
                switch (t.getStatus()) {
                case BUTTERED:
                    toBeJammedQueue.put(t);
                    break;
                case JAMMED:
                    toBeButteredQueue.put(t);
                    break;
                default:
                    finishedQueue.put(t);
                }
            }
        } catch (InterruptedException e) {
            System.out.println("Merger interrupted");
        }
        System.out.println("Merger off");
    }
}

public class BlockQueue {
    public static void main(String[] args) throws Exception {
        ToastQueue dryQueue = new ToastQueue(), butteredQueue = new ToastQueue(), toBeButteredQueue = new ToastQueue(), jammedQueue = new ToastQueue(), toBeJammedQueue = new ToastQueue(), finishedQueue = new ToastQueue();
        ExecutorService exec = Executors.newCachedThreadPool();
        exec.execute(new Toaster(dryQueue));
        exec.execute(new Alternator(dryQueue, toBeButteredQueue,
                toBeJammedQueue));
        exec.execute(new Butterer(toBeButteredQueue, butteredQueue));
        exec.execute(new Jammer(toBeJammedQueue, jammedQueue));
        exec.execute(new Merger(butteredQueue, jammedQueue, toBeButteredQueue,
                toBeJammedQueue, finishedQueue));
        exec.execute(new Eater(finishedQueue));
        TimeUnit.SECONDS.sleep(5);
        exec.shutdownNow();
    }
} 
//dryQueue:制作的干吐司
//toBeButteredQueue:将要被涂黄油的吐司
//toBeJammedQueue将要被涂酱的吐司
//butteredQueue、jammedQueue已经被涂了的
//Merger 整合工作,如果是黄油就进行涂酱,反之,(异步)如果是ready就进入完成队列

管道实现

//Todo

死锁

  • 互斥条件。进程对所分配到的资源进行排他性使用,即在一段时间内,某资源只能被一个进程占用。如果此时还有其他进程请求该资源,则请求进程只能等待,直至占有该资源的进程用毕释放。

  • 请求和保持条件。进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己以获得的资源保持不放。

  • 不可抢占条件。进程已获得的资源在未使用完之前不能被抢占,只能在进程使用完时由自己释放。

  • 循环等待条件。在发生死锁时,必然存在一个进程—资源的循环链,即进程集合{P0,P1,P2,P3,...,Pn}中的P0正在等待P1占用的资源,P1正在等待P2占用的资源,... ... ,Pn正在等待已被P0占用的资源。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容