问题描述:1个父线程,并发生成N(N作为参数传入)个子线程。设定全局变量 g_sum=0,每个子进程在 0至200中随机选择一个数;
若子线程的进程ID是奇数则g_sum=g_sum-随机数,
若子线程的进程ID是偶数则g_sum=g_sum+随机数,
每个子线程对g_sum操作完成后都要通知父线程,父线程收到通知后输出“子线程{进程ID}对g_sum进行了[加/减]{随机数}操作,当前g_sum={新值}”,父进程将每次g_sum的新值进行记录,并对已记录的数组进行升序排列,每次重新排列后进行一次输出。
想法一 回调方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| public class ThreadTest { public static int g_sum = 0; public static List<Integer> g_sumList = new ArrayList<Integer>(); public static Object o= new Object();
@SuppressWarnings("unchecked") public ThreadTest() { super(); this.g_sumList.add(g_sum); }
public static void callBack(int id, int num, int flag) { String mark = flag == 1 ? "加" : "减"; System.out.println("子线程" + id + ":对g_num进行了" + mark + "" + num + "操作,当前g_sum=" + g_sum); g_sumList.add(g_sum); Collections.sort(g_sumList); SimpleDateFormat sdf = new SimpleDateFormat(); sdf.applyPattern("yyyy-MM-dd HH:mm:ss a"); Date date = new Date(); System.out.println(sdf.format(date)+" g_sum历史值升序为:"); System.out.println(g_sumList); System.out.println(); } public void generateThreads(int N) { int randomNum; for (int id = 1; id <= N; id++) { randomNum = (int) (Math.random() * 200); MyRunnable myRunnable = new MyRunnable(id, randomNum); Thread t=new Thread(myRunnable); t.start(); } }
public static void main(String[] args) { ThreadTest test = new ThreadTest(); test.generateThreads(10); } }
|
MyRunnable.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class MyRunnable implements Runnable { private int id; private int randomNum;
public MyRunnable(int id, int randomNum) { super(); this.id = id; this.randomNum = randomNum; } @Override public void run() { synchronized (ThreadTest.o) { if (id % 2 == 0) { ThreadTest.g_sum += randomNum; ThreadTest.callBack(id, randomNum, 1); } else { ThreadTest.g_sum -= randomNum; ThreadTest.callBack(id, randomNum, 0); } }
}
}
|
子线程和父线程之间其实并没有进行通信,打印信息的静态回调方法callBack()虽然是在主类中定义,但是却是在子线程中调用的,而不是子线程将信息传递并通知给主线程,然后主线程打印。
想法二 消息队列
ThreadTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public class ThreadTest { public static int g_sum = 0; public static Deque<Message> messageDeque = new ArrayDeque(); public List<Integer> g_sumList = new ArrayList<Integer>(); public static Object lock= new Object(); public ThreadTest() { super(); this.g_sumList.add(g_sum); } public void generateThreads(int N) { int randomNum; for (int id = 1; id <= N; id++) { randomNum = (int) (Math.random() * 200); MyRunnable myRunnable = new MyRunnable(id, randomNum); Thread t=new Thread(myRunnable); t.start(); } } public static void main(String[] args) throws InterruptedException { System.out.print("请输入问题规模:"); Scanner in = new Scanner(System.in); int N = in.nextInt(); ThreadTest test = new ThreadTest(); synchronized (lock) { test.generateThreads(N); while(true) { if(messageDeque.isEmpty()) { lock.wait(); } while(!messageDeque.isEmpty()) { Message mess = messageDeque.pop(); System.out.println("子线程"+mess.tid+"进行了"+mess.op+""+mess.randomNum+"操作,当前g_sum="+mess.g_sum); test.g_sumList.add(mess.g_sum); Collections.sort(test.g_sumList); System.out.println(mess.opeTime+" g_sum历史值升序为:"); System.out.println(test.g_sumList); System.out.println(); } } } } }
|
MyRunnable.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| public class MyRunnable implements Runnable { private int tid; private int randomNum;
public MyRunnable(int id, int randomNum) { super(); this.tid = id; this.randomNum = randomNum; } @Override public void run() { synchronized (ThreadTest.lock) { SimpleDateFormat sdf = new SimpleDateFormat(); sdf.applyPattern("yyyy-MM-dd HH:mm:ss a"); String opeTime = sdf.format(new Date()); if (tid % 2 == 0) { ThreadTest.g_sum += randomNum; Message message = new Message(tid, "加", randomNum,ThreadTest.g_sum,opeTime); ThreadTest.messageDeque.add(message); ThreadTest.lock.notifyAll(); } else { ThreadTest.g_sum -= randomNum; Message message = new Message(tid, "减", randomNum,ThreadTest.g_sum,opeTime); ThreadTest.messageDeque.add(message); ThreadTest.lock.notifyAll(); } try { int sleepTime = (int)(Math.random() * 500); Thread.sleep(sleepTime); } catch (InterruptedException e) { e.printStackTrace(); } }
} public class Message{ public int tid; public String op; public int randomNum; public int g_sum; public String opeTime; public Message(int tid, String op, int randomNum,int g_sum ,String time) { super(); this.tid = tid; this.op = op; this.randomNum = randomNum; this.g_sum = g_sum; this.opeTime=time; } }
}
|
主线程并发创建N个子线程后,转为阻塞等待状态,等待lock解锁获得执行权且消息队列非空,然后一次性打印消息队列中已经存放的消息。
子线程在进行“加减”操作完成后,创建一个消息(包含线程id、随机数、操作类型、操作结果、操作时间信息),并把这个消息添加到消息队列(一个静态全局的队列),然后Notifiy(通知)唤醒主线程,通知它消息队列有消息可以打印了。