多线程

多线程

http://www.nowcoder.com/questionTerminal/cd99fbc6154d4074b4da0e74224a1582

刚开始a、b、c、d的等待池中都没有ABCD四个线程,所以ABCD都有机会执行打印方法里打同步代码

A线程执行打印完毕调用b.notify()从b的等待池的中移走一个线程,a.wait()进入a的等待池(a对象等待池:A线程)
B线程执行打印完毕调用c.notify()从b的等待池的中移走一个线程,b.wait()进入a的等待池(b对象等待池:B线程)
C线程执行打印完毕调用d.notify()从b的等待池的中移走一个线程,c.wait()进入a的等待池(c对象等待池:C线程)
D线程执行打印完毕调用a.notify()从b的等待池的中移走一个线程,d.wait()进入a的等待池(d对象等待池:D线程,a对象等待池:没有A线程)
D线程执行完后a和b线程池里都没有A线程,而BCD线程都不能同时获取它们执行打印所需要的两个对象锁标记,所以此时只有A线程能执行打印,
A线程第二次打印往后把b对象等待池的一个线程移走,因为b的等待池只有B线程,所以B线程被移走放入锁池,此时只有B线程能执行打印,以此类推,B打印后只能执行C,C打印后只能执行D,D打印后只能执行A...

因为刚开始一起启用四个线程后不知道哪个线程会先执行打印,所以需要控制线程启动后的首次执行顺,我的做法是在创建线程的类里加两个静态整型变量newIndex和runIndex,每当创建线程的对象是就把当前线程的Id设为newIndex的值,然后newIndex加1,每个线程首次执行打印后都把runIndex加1,当线程执行到synchronized里先判断当前线程的id是否大于runIndex,如果大于说明这个线程是首次执行且还不应该到它执行打印,所以把它在外层synchronized的对象上休眠等待它上一个线程执行答应后唤醒它。

每次一个线程打印完后就休眠了,为了控制每个线程打印完了最后一次直接结束而不是进入休眠所以在打印后需要判断一下是否当前线程已经完成了所以打印次数。

import java.util.Scanner;

/**
 * 题目描述
 * 问题描述:有4个线程和1个公共的字符数组。
 * 线程1的功能就是向数组输出A,线程2的功能就是向字符输出B,线程3的功能就是向数组输出C,
 * 线程4的功能就是向数组输出D。要求按顺序向数组赋值ABCDABCDABCD,ABCD的个数由线程函数1的参数指定
 */
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()){
            int num = scanner.nextInt();
            Object a = new Object();
            Object b = new Object();
            Object c = new Object();
            Object d = new Object();
            Thread thread1 = new Thread(new ThreadPrintAbcd("A",a,b,num));
            Thread thread2 = new Thread(new ThreadPrintAbcd("B",b,c,num));
            Thread thread3 = new Thread(new ThreadPrintAbcd("C",c,d,num));
            Thread thread4 = new Thread(new ThreadPrintAbcd("D",d,a,num));

            thread1.start();
            thread2.start();
            thread3.start();
            thread4.start();
        }
    }
}
class ThreadPrintAbcd implements Runnable{
    private static int newIndex=0;
    private static int runIndex=0;
    private boolean isFirstRun=true;
    private Object self;
    private Object next;
    private String name;
    private int id;
    private int num;

    public ThreadPrintAbcd(String name,Object self,Object next,int num){
        id = newIndex++;
        this.name = name;
        this.self = self;
        this.next = next;
        this.num = num;
    }
    @Override
    public void run() {
        while (num > 0){
        synchronized(self){
                if(id > runIndex){
                    try {
                        self.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.print(name);
                if(isFirstRun){
                    runIndex ++;
                    isFirstRun=false;
                }
            synchronized (next) {
                next.notify();
            }
                num--;
                if(num >0){
                    try {
                        self.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
全部评论

相关推荐

行云流水1971:这份实习简历的优化建议: 结构清晰化:拆分 “校园经历”“实习经历” 板块(当前内容混杂),按 “实习→校园→技能” 逻辑排版,求职意向明确为具体岗位(如 “市场 / 运营实习生”)。 经历具象化:现有描述偏流程,需补充 “动作 + 数据”,比如校园活动 “负责宣传” 可加 “运营公众号发布 5 篇推文,阅读量超 2000+,带动 300 + 人参与”;实习内容补充 “协助完成 XX 任务,效率提升 X%”。 岗位匹配度:锚定目标岗位能力,比如申请运营岗,突出 “内容编辑、活动执行” 相关动作;申请市场岗,强化 “资源对接、数据统计” 细节。 信息精简:删减冗余表述(如重复的 “负责”),用短句分点,比如 “策划校园招聘会:联系 10 + 企业,组织 200 + 学生参与,到场率达 85%”。 技能落地:将 “Office、PS” 绑定经历,比如 “用 Excel 整理活动数据,输出 3 份分析表;用 PS 设计 2 张活动海报”,避免技能单独罗列。 优化后需强化 “经历 - 能力 - 岗位需求” 的关联,让实习 / 校园经历的价值更直观。 若需要进一步优化服务,私信
实习,投递多份简历没人回...
点赞 评论 收藏
分享
评论
12
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务