zoukankan      html  css  js  c++  java
  • 并发(一)

    这个月,总结一下thread的相关知识,把基础知识弄得更牢固一下,学习先增加深度在扩展广度。

    声明:文章内容以及部分代码示例,参考了《Thinking in Java》(Java编程思想)这本书。

    该书绝对是java从业人员的宝典之一。强烈推荐。

    1 并发

    并发通常是提高运行在单处理器上的程序的性能。

    一般它或提高程序执行效率,或为设计某些类型的程序提供更易用的模块,或两者都有。

     在这里说一下线程安全的概念,多线程访问同一代码,不会产生不确定的结果,这样的话我们就说线程是安全的。

    2 基本线程机制

    2.1 定义任务,创建线程

    一般是两种方式,一是继承一个thread类,另一种是实现Runnable接口。

    下面给出代码示例:

     1 public class LiftOff implements Runnable{
     2 
     3     protected int countDown = 10;
     4     private static int taskCount = 0;
     5     // 标识符id可以用来区分任务的多个实例,它是final的,
     6     // 因为它一旦被初始化之后就不希望被修改
     7     private final int id = taskCount++;
     8     public LiftOff() {}
     9     public LiftOff(int countDown) {
    10         
    11     }
    12     public String status() {
    13         return "#" + id + "(" + 
    14     (countDown > 0 ? countDown : "LiftOff") + ").";
    15     }
    16     public void run() {
    17         
    18         while(countDown-- > 0){
    19             System.out.println(status());
    20             Thread.yield();
    21         }
    22     }
    23 }
    View Code
    1 public class ThreadDemo01 extends Thread{
    2     public static void main(String args[]){
    3         LiftOff lift = new LiftOff();
    4         lift.run();
    5     }
    6 }
    View Code
    1 public class ThreadDemo02 extends Thread{
    2     public static void main(String args[]){
    3         Thread thread = new Thread(new LiftOff());
    4         thread.start();
    5     }
    6 
    7 }
    View Code

    执行结果如下:

    #0(9).
    #0(8).
    #0(7).
    #0(6).
    #0(5).
    #0(4).
    #0(3).
    #0(2).
    #0(1).
    #0(LiftOff).
    View Code

    大家查看API会发现,Thread类继承了Runnable接口,所以,线程最终是通过Runnable接口来实现的。推荐使用Runnable接口的方式,因为这样它还可以继承其它的类,增加自身的灵活性。

    下面给出一个驱动多线程的示例:

     1 public class ThreadDemo03 {
     2 
     3     public static void main(String[] args) {
     4 
     5         for (int i = 0; i < 5; i++) {
     6             new Thread(new LiftOff()).start();
     7         }
     8     }
     9 
    10 }
    View Code

    2.2 使用Executor

    书中写明,在JAVA 6中,Executor是启动任务的优选方法,但是目前在JAVA 8中,是不是优选,我不知道。

    Executor相当于客户端和线程之间的一个桥梁,由它执行任务。

    常用的Executor有newCachedThreadPool(首选), FixedThreadPool(需指定线程数量), SingleThreadExcutor等。

     1 import java.util.concurrent.ExecutorService;
     2 import java.util.concurrent.Executors;
     3 
     4 public class ThreadDemo04 {
     5     public static void main(String[] args) {
     6 
     7         ExecutorService service = Executors.newCachedThreadPool();
     8         
     9         // ExecutorService service = Executors.newFixedThreadPool(2);
    10         // ExecutorService service = Executors.newSingleThreadExecutor();
    11         
    12         for (int i = 0; i < 5; i++) {
    13             service.execute(new LiftOff());
    14         }
    15         // shutDown方法,拒绝接受新的任务。我认为类似于io的close
    16         service.shutdown();
    17         System.out.println("------------");
    18     }
    19 }
    View Code

    2.3 从任务中产生返回值

    Runnable只能执行任务,不能返回结果和异常。为了返回结果,可以实现Callable接口。

    代码示例如:

     1 import java.util.LinkedList;
     2 import java.util.List;
     3 import java.util.concurrent.Callable;
     4 import java.util.concurrent.ExecutionException;
     5 import java.util.concurrent.ExecutorService;
     6 import java.util.concurrent.Executors;
     7 import java.util.concurrent.Future;
     8 
     9 public class ThreadDemo06 {
    10 
    11     public static void main(String[] args) {
    12 
    13         ExecutorService service = Executors.newCachedThreadPool();
    14         List<Future<String>> list = new LinkedList<Future<String>>();
    15         for (int i=0 ; i< 10 ; i++){
    16             list.add(service.submit(new TaskWithResult(i)));
    17         }
    18         for (Future<String> fs : list) {
    19             try {
    20                 // get方法会或许返回值,如果任务尚未执行结束,会一直等待,造成阻塞
    21                 // 可以用isDone方法来判断,任务是否执行结束
    22                 System.out.println("future done? " + fs.isDone());
    23                 System.out.println(fs.get());
    24             } catch (InterruptedException | ExecutionException e) {
    25                 e.printStackTrace();
    26                 return;
    27             } finally {
    28                 service.shutdown();
    29             }
    30         } 
    31     }
    32 }
    33 
    34 class TaskWithResult implements Callable<String> {
    35 
    36     private int id;
    37     public TaskWithResult (int id) {
    38         this.id = id;
    39     }
    40     @Override
    41     public String call() throws Exception {
    42         return "result of TaskWithResult " + id;
    43     }
    44 }
    View Code

    执行结果:

    future done? true
    result of TaskWithResult 0
    future done? true
    result of TaskWithResult 1
    future done? true
    result of TaskWithResult 2
    future done? true
    result of TaskWithResult 3
    future done? true
    result of TaskWithResult 4
    future done? true
    result of TaskWithResult 5
    future done? true
    result of TaskWithResult 6
    future done? true
    result of TaskWithResult 7
    future done? true
    result of TaskWithResult 8
    future done? true
    result of TaskWithResult 9
    View Code

    2.4 后台线程

    所谓后台线程,是指在程序运行的时候在后台提供一种通用服务的线程,并且这种线程并不属于程序中不可或缺的部分。因此,当所有的后台线程结束时,程序也就终止了,同时杀死进程中的所有后台线程。(摘自《Java编程思想》第21章)

    代码示例如下:

     1 import java.util.concurrent.TimeUnit;
     2 
     3 public class SimpleDaemons implements Runnable {
     4 
     5     @Override
     6     public void run() {
     7 
     8         while (true) {
     9             try {
    10                 TimeUnit.MICROSECONDS.sleep(100);
    11                 System.out.println(Thread.currentThread() + " " + this);
    12             } catch (InterruptedException e) {
    13                 e.printStackTrace();
    14                 System.out.println("sleep() intertupted");
    15             }
    16         }
    17     }
    18     
    19     public static void main(String[] args) throws InterruptedException {
    20         for (int i = 0; i < 10; i++) {
    21 
    22             Thread daemon = new Thread(new SimpleDaemons());
    23             daemon.setDaemon(true);
    24             daemon.start();
    25         }
    26         System.out.println("All daemons started");
    27         TimeUnit.MICROSECONDS.sleep(175);
    28     }
    29 }
    View Code
  • 相关阅读:
    正则表达式入门教程
    js获取class
    锋利的jQuery第6章 jQuery与Ajax的应用
    显示隐藏左侧菜单
    unicode转为汉字
    $.ajax
    .ashx文件
    c#正则表达式
    调试发现的小错误
    sql2005连接不到本地数据库
  • 原文地址:https://www.cnblogs.com/lihao007/p/7538156.html
Copyright © 2011-2022 走看看