zoukankan      html  css  js  c++  java
  • 关于多线程练习的几个题目

    第一题:现有的程序代码模拟产生了16个日志对象,并且需要运行16秒才能打印完这些日志,请在程序中增加4个线程去调用parseLog()方法来分头打印这16个日志对象,程序只需要运行4秒即可打印完这些日志对象。原始代码如下:

    交给四个线程,打印16个日志对象信息,启动四个线程容易,但是怎样将这16个日志对象交给4个线程,这时候我们用阻塞队列,将要打印的日志信息放到阻塞队列中,四个线程启动时都从阻塞队列中取数据,取完后打印即可。阻塞队列的大小可以自行设置。

    修改为多线程打印日志信息后的代码及注释参考下文:

     1 public class Test {
     2     public static void main(String[] args) {
     3         System.out.println("begin:" + (System.currentTimeMillis() / 1000)); 
     4         final BlockingQueue<String> queue = new ArrayBlockingQueue<String>(16);
     5         //启动4个线程
     6         for(int i = 0; i < 4; i++){
     7             new Thread(new Runnable(){
     8                 @Override
     9                 public void run() {
    10                     //不断从阻塞队列中取出数据并打印
    11                     while(true){
    12                         String log;
    13                         try {
    14                             log = queue.take();
    15                             parseLog(log);
    16                         } catch (Exception e) {
    17                             e.printStackTrace();
    18                         }
    19                     }
    20                 }
    21                 
    22             }).start();
    23         }
    24         for (int i = 0; i < 16; i++) { // 这行代码不能改动
    25             final String log = "" + (i + 1);// 这行代码不能改动,生成的日志信息
    26             {
    27                 try {
    28                       queue.put(log);                //将日志信息放入阻塞队列
    29                       //Test.parseLog(log);            //打印日志信息
    30                 } catch (Exception e) {
    31                     e.printStackTrace();
    32                 }
    33             }
    34         }
    35     }
    36     // parseLog方法内部的代码不能改动
    37     public static void parseLog(String log) {
    38         System.out.println(log + ":" + (System.currentTimeMillis() / 1000));
    39         try {
    40             Thread.sleep(1000);
    41         } catch (InterruptedException e) {
    42             e.printStackTrace();
    43         }
    44     }
    45 }

    第二题:现成程序中的Test类中的代码在不断地产生数据,然后交给TestDo.doSome()方法去处理,就好像生产者在不断地产生数据,消费者在不断消费数据。请将程序改造成有10个线程来消费生成者产生的数据,这些消费者都调用TestDo.doSome()方法去进行处理,故每个消费者都需要一秒才能处理完,程序应保证这些消费者线程依次有序地消费数据,只有上一个消费者消费完后,下一个消费者才能消费数据,下一个消费者是谁都可以,但要保证这些消费者线程拿到的数据是有顺序的。原始代码如下:

    解答:

    10个线程,依次消费数据,仍然是将待消费数据放入阻塞队列,让10个线程去取数据消费,所不同的是这次消费必须一个一个线程来,而不再是10个线程一起去取,因此用到了线程的同步。同步方法有多种,这里使用Semaphore来进行线程间的同步,代码及注释如下:

     1 public class Test {
     2     
     3         public static void main(String[] args) {
     4             
     5             final SynchronousQueue<String> queue = new SynchronousQueue<String>();
     6             final Semaphore semaphore = new Semaphore(1);
     7             //10个线程,分别消费数据,依旧是从阻塞队列中获取数据
     8             for(int i=0; i < 10; i++){
     9                 new Thread(new Runnable(){
    10                     @Override
    11                     public void run() {
    12                         try {
    13                             semaphore.acquire();
    14                             String input = queue.take();
    15                             String output = TestDo.doSome(input);
    16                             System.out.println(Thread.currentThread().getName()+ ":" + output);
    17                             semaphore.release();
    18                         } catch (Exception e) {
    19                             e.printStackTrace();
    20                         }
    21                     }
    22                     
    23                 }).start();
    24             }
    25             
    26             System.out.println("begin:"+(System.currentTimeMillis()/1000));
    27             for(int i=0;i<10;i++){  //这行不能改动
    28                 String input = i+"";  //这行不能改动,不断产生数据
    29                 try {
    30                     queue.put(input);
    31                 } catch (Exception e) {
    32                     e.printStackTrace();
    33                 }
    34                 //String output = TestDo.doSome(input);//不断消费数据
    35                 //System.out.println(Thread.currentThread().getName()+ ":" + output);
    36             }
    37         }
    38     }
  • 相关阅读:
    AC日记——[HNOI2008]GT考试 bzoj 1009
    AC日记——[SCOI2009]游戏 bzoj 1025
    AC日记——[HNOI2010]BOUNCE 弹飞绵羊 洛谷 P3203
    AC日记——旅游 bzoj 2157
    NOIP模拟2017.6.11解题报告
    AC日记——【模板】Link Cut Tree 洛谷 P3690
    AC日记——[SDOI2010]大陆争霸 洛谷 P3690
    [NOI2010]超级钢琴 倍增
    [HNOI2004]L语言 字典树 记忆化搜索
    对拍
  • 原文地址:https://www.cnblogs.com/yolanda-lee/p/5489182.html
Copyright © 2011-2022 走看看