`
dasheng
  • 浏览: 148568 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

<java编程思想>学习笔记21 第21章 并发(多线程)(1)

阅读更多

1,到目前为止,你学到的都是有关顺序编程的知识,即程序中的所有的事物在任意时刻都只能执行一个步骤。

 

2,java是一门多线程的语言,并且提出了并发问题。

 

3,你无法选择何时在你的java程序中出现线程,仅仅是你没有启动线程并不代表你就可以回避编写使用线程的代码。

 

例如,Web系统是最常见的java应用系统之一,而基本的Web类库、Servlet具有天生的多线程特性,这很重要,

 

因为Web服务器经常包含多个处理器,而并发是充分利用这些处理器的理想方式。即使是Servlet这样的看起来很简单的

 

情况。你也必须理解并发问题,从而正确的使用它们。图形化界面也是类似的情况,尽管SWing和SWT类库都拥有针对

 

线程安全的机制,但是不理解并发,你就很难了解如何正确的使用它们。

 

4,定义任务,线程可以驱动任务,因此你需要一种描述任务的方式,这可以有Runnable接口来提供。

 

public class LiftOff implements Runnable {
  protected int countDown = 10; // Default
  private static int taskCount = 0;
  private final int id = taskCount++;
  public LiftOff() {}
  public LiftOff(int countDown) {
    this.countDown = countDown;
  }
  public String status() {
    return "#" + id + "(" +
      (countDown > 0 ? countDown : "Liftoff!") + "), ";
  }
  public void run() {
    while(countDown-- > 0) {
      System.out.print(status());
      Thread.yield();   //是切换到别的线程的时机了
    }
  }
} ///:~

 

 

应用这个任务:

 

public class MainThread {
  public static void main(String[] args) {
    LiftOff launch = new LiftOff();
    launch.run();
  }
} /* Output

 

输出结果是:

 

#0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2), #0(1), #0(Liftoff!),

 

 

4,也可以将Runnable对象转变为工作任务的传统方式把它提交到Thread的构造器。

 

public class BasicThreads {
  public static void main(String[] args) {
    Thread t = new Thread(new LiftOff());
    t.start();
    System.out.println("Waiting for LiftOff");
  }
} /* Output: (90% match)

 

Start方法迅速返回的。

可以启动更多的任务:

 

public class MoreBasicThreads {
  public static void main(String[] args) {
    for(int i = 0; i < 5; i++)
      new Thread(new LiftOff()).start();
    System.out.println("Waiting for LiftOff");
  }
} /* Output

结果是:

 

Waiting for LiftOff
#0(9), #1(9), #3(9), #4(9), #2(9), #1(8), #4(8), #0(8), #3(8), #2(8), #1(7), #4(7), #3(7), #2(7), #0(7), #1(6), #4(6), #3(6), #2(6), #1(5), #4(5), #0(6), #3(5), #2(5), #4(4), #0(5), #3(4), #1(4), #2(4), #4(3), #0(4), #3(3), #2(3), #0(3), #1(3), #3(2), #4(2), #2(2), #0(2), #4(1), #2(1), #1(2), #3(1), #4(Liftoff!), #1(1), #0(1), #3(Liftoff!), #1(Liftoff!), #2(Liftoff!), #0(Liftoff!),

 

5,使用Executor

 

java SE5的java.util.concurrent包中的执行器(Exector)将为你管理Thread对象,从而简化了并发编程。

 

Excutor在客户端和任务执行之间提供了一个间接层:与客户端直接执行任务不同,这个中介对象将执行任务。

 

Excutor允许你管理异步任务,而无需显式的管理现成的生命周期,Executor是java SE 5/6启动任务的优先选择。

 

public class CachedThreadPool {
  public static void main(String[] args) {
    ExecutorService exec = Executors.newCachedThreadPool();
    for(int i = 0; i < 5; i++)
      exec.execute(new LiftOff());
    exec.shutdownNow();
    System.out.println("shutdown now!!");
  }
} /* Output:

 

shutdown()方法可以防止新的任务提交到这个Executor。运行完已经提交的任务马上退出。

shutdownnow()方法立即关闭。不运行现在的任务,立即退出。

 

public class FixedThreadPool {
  public static void main(String[] args) {
    // Constructor argument is number of threads:
    ExecutorService exec = Executors.newFixedThreadPool(5);  //固定大小的线程池
    for(int i = 0; i < 5; i++)
      exec.execute(new LiftOff());
    exec.shutdown();
  }
} /* Output: (Sample)

 

 

public class SingleThreadExecutor {
  public static void main(String[] args) {
    ExecutorService exec =  Executors.newSingleThreadExecutor();//相当于线程数为1的的newFixedThreadPool
    for(int i = 0; i < 5; i++)
      exec.execute(new LiftOff());
    exec.shutdown();
  }
} /* Output

 

6,如果希望任务有返回值,用Callable做接口

 

class TaskWithResult implements Callable<String> {
  private int id;
  public TaskWithResult(int id) {
    this.id = id;
  }
  public String call() {
    return "result of TaskWithResult " + id;
  }
}

public class CallableDemo {
  public static void main(String[] args) {
    ExecutorService exec = Executors.newCachedThreadPool();
    ArrayList<Future<String>> results =
      new ArrayList<Future<String>>();
    for(int i = 0; i < 10; i++)
      results.add(exec.submit(new TaskWithResult(i)));
    for(Future<String> fs : results)
      try {
        // get() blocks until completion:
       if(fs.isDone())
        System.out.println(fs.get());
      } catch(InterruptedException e) {
        System.out.println(e);
        return;
      } catch(ExecutionException e) {
        System.out.println(e);
      } finally {
        exec.shutdown();
      }
  }
} /* Output:

运行结果是:

result of TaskWithResult 0
result of TaskWithResult 1
result of TaskWithResult 2
result of TaskWithResult 3
result of TaskWithResult 4
result of TaskWithResult 5
result of TaskWithResult 6
result of TaskWithResult 7
result of TaskWithResult 8
result of TaskWithResult 9

 

6,休眠调用sleep。

 

public class SleepingTask extends LiftOff {
  public void run() {
    try {
      while(countDown-- > 0) {
        System.out.print(status());
        // Old-style:
         Thread.sleep(500);
        // Java SE5/6-style:
        //TimeUnit.MILLISECONDS.sleep(100);
      }
    } catch(InterruptedException e) {
      System.err.println("Interrupted");
    }
  }
  public static void main(String[] args) {
    ExecutorService exec = Executors.newCachedThreadPool();
    for(int i = 0; i < 5; i++)
      exec.execute(new SleepingTask());
    exec.shutdown();
  }
} /* Output:

 

7,优先级

 

public class SimplePriorities implements Runnable {
  private int countDown = 5;
  private volatile double d; // No optimization
  private int priority;
  public SimplePriorities(int priority) {
    this.priority = priority;
  }
  public String toString() {
    return Thread.currentThread() + ": " + countDown;
  }
  public void run() {
    Thread.currentThread().setPriority(priority);
    while(true) {
      // An expensive, interruptable operation:
      for(int i = 1; i < 100000; i++) {
        d += (Math.PI + Math.E) / (double)i;
        if(i % 1000 == 0)
          Thread.yield();
      }
      System.out.println(this);
      if(--countDown == 0) return;
    }
  }
  public static void main(String[] args) {
    ExecutorService exec = Executors.newCachedThreadPool();
    for(int i = 0; i < 5; i++)
      exec.execute(
        new SimplePriorities(Thread.MIN_PRIORITY));
    exec.execute(
        new SimplePriorities(Thread.MAX_PRIORITY));
    exec.shutdown();
  }
} /* Output: (70% match)

 

 

8,后台线程

 

所有后台(daemon)线程,是指在程序运行的时候在后台提供一种通用的服务。并且这种线程并不属于程序的不可或缺

 

的部分。因此,当所有的非后台线程结束时,程序也就终止了。同时会杀死所有后台线程。反过来,只有任何非后台线程还

 

在运行,程序就不会终止。

 

 

public class SimpleDaemons implements Runnable {
  public void run() {
    try {
      while(true) {
        TimeUnit.MILLISECONDS.sleep(100);
        print(Thread.currentThread() + " " + this);
      }
    } catch(InterruptedException e) {
      print("sleep() interrupted");
    }
  }
  public static void main(String[] args) throws Exception {
    for(int i = 0; i < 10; i++) {
      Thread daemon = new Thread(new SimpleDaemons());
      daemon.setDaemon(true); // Must call before start()
      daemon.start();
    }
    print("All daemons started");
    TimeUnit.MILLISECONDS.sleep(100);
  }
} /

 

运行结果:

 

All daemons started
Thread[Thread-3,5,main] SimpleDaemons@15ff48b
Thread[Thread-8,5,main] SimpleDaemons@1be2d65
Thread[Thread-6,5,main] SimpleDaemons@affc70
Thread[Thread-0,5,main] SimpleDaemons@1e63e3d
Thread[Thread-9,5,main] SimpleDaemons@1004901
Thread[Thread-2,5,main] SimpleDaemons@1b90b39
Thread[Thread-5,5,main] SimpleDaemons@18fe7c3
Thread[Thread-7,5,main] SimpleDaemons@b8df17
Thread[Thread-4,5,main] SimpleDaemons@13e8d89
Thread[Thread-1,5,main] SimpleDaemons@9664a1

后台线程会在不执行finally子句的情况下终止其run()方法

 

class ADaemon implements Runnable {
  public void run() {
    try {
      print("Starting ADaemon");
      TimeUnit.SECONDS.sleep(1);
    } catch(InterruptedException e) {
      print("Exiting via InterruptedException");
    } finally {
      print("This should always run?");
    }
  }
}

public class DaemonsDontRunFinally {
  public static void main(String[] args) throws Exception {
    Thread t = new Thread(new ADaemon());
    t.setDaemon(true);
    t.start();
  }
} /* Output:
Starting ADaemon
*///:~

 

结果:

Starting ADaemon

 

没有运行finally子句。

 

9,其他的形式的线程任务:

 

public class SimpleThread extends Thread {
  private int countDown = 5;
  private static int threadCount = 0;
  public SimpleThread() {
    // Store the thread name:
    super(Integer.toString(++threadCount));
    //start();
  }
  public String toString() {
    return "#" + getName() + "(" + countDown + "), ";
  }
  public void run() {
    while(true) {
      System.out.print(this);
      if(--countDown == 0)
        return;
    }
  }
  public static void main(String[] args) {
    for(int i = 0; i < 5; i++)
      new SimpleThread().start();
  }
} /* Output:

 

和以下的:

 

public class SelfManaged implements Runnable {
  private int countDown = 5;
  private Thread t = new Thread(this);
  public SelfManaged() { t.start(); }
  public String toString() {
    return Thread.currentThread().getName() +
      "(" + countDown + "), ";
  }
  public void run() {
    while(true) {
      System.out.print(this);
      if(--countDown == 0)
        return;
    }
  }
  public static void main(String[] args) {
    for(int i = 0; i < 5; i++)
      new SelfManaged();
  }
} /* Output:

 

10,join入一个线程

 

class Sleeper extends Thread {
  private int duration;
  public Sleeper(String name, int sleepTime) {
    super(name);
    duration = sleepTime;
    start();
  }
  public void run() {
    try {
      sleep(duration);
    } catch(InterruptedException e) {
      print(getName() + " was interrupted. " +
        "isInterrupted(): " + isInterrupted());
      return;
    }
    print(getName() + " has awakened");
  }
}

class Joiner extends Thread {
  private Sleeper sleeper;
  public Joiner(String name, Sleeper sleeper) {
    super(name);
    this.sleeper = sleeper;
    start();
  }
  public void run() {
   try {
      sleeper.join();
    } catch(InterruptedException e) {
      print("Interrupted");
    }
    print(getName() + " join completed");
  }
}

public class Joining {
  public static void main(String[] args) {
    Sleeper
      sleepy = new Sleeper("Sleepy", 1500),
      grumpy = new Sleeper("Grumpy", 1500);
    Joiner
      dopey = new Joiner("Dopey", sleepy),
      doc = new Joiner("Doc", grumpy);
    grumpy.interrupt();
  }
} /* Output:

 

11,无法用try,catch来捕获异常

 

public class ExceptionThread implements Runnable {
  public void run() {
    throw new RuntimeException();
  }
  public static void main(String[] args) {
    ExecutorService exec = Executors.newCachedThreadPool();
    exec.execute(new ExceptionThread());
  }
} ///:~

 

 

public class NaiveExceptionHandling {
  public static void main(String[] args) {
    try {
      ExecutorService exec =
        Executors.newCachedThreadPool();
      exec.execute(new ExceptionThread());
    } catch(RuntimeException ue) {
      // This statement will NOT execute!
      System.out.println("Exception has been handled!");
    }
  }
} ///:~

无法捕获异常:

 

Exception in thread "pool-1-thread-1" java.lang.RuntimeException
 at ExceptionThread.run(ExceptionThread.java:7)
 at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
 at java.lang.Thread.run(Unknown Source)

需要banding一个异常处理器:

 

class ExceptionThread2 implements Runnable {
  public void run() {
    Thread t = Thread.currentThread();
    System.out.println("run() by " + t);
    System.out.println(
      "eh = " + t.getUncaughtExceptionHandler());
    throw new RuntimeException();
  }
}

class MyUncaughtExceptionHandler implements
Thread.UncaughtExceptionHandler {
  public void uncaughtException(Thread t, Throwable e) {
    System.out.println("caught " + e);
  }
}

class HandlerThreadFactory implements ThreadFactory {
  public Thread newThread(Runnable r) {
    System.out.println(this + " creating new Thread");
    Thread t = new Thread(r);
    System.out.println("created " + t);
    t.setUncaughtExceptionHandler(
      new MyUncaughtExceptionHandler());
    System.out.println(
      "eh = " + t.getUncaughtExceptionHandler());
    return t;
  }
}

public class CaptureUncaughtException {
  public static void main(String[] args) {
    ExecutorService exec = Executors.newCachedThreadPool(
      new HandlerThreadFactory());
    exec.execute(new ExceptionThread2());
  }
} /* Output: (90% match)

 

结果是:

 

HandlerThreadFactory@42719c creating new Thread
created Thread[Thread-0,5,main]
eh = MyUncaughtExceptionHandler@119298d
run() by Thread[Thread-0,5,main]
eh = MyUncaughtExceptionHandler@119298d
caught java.lang.RuntimeException
捕获了异常。

 

 

 

分享到:
评论

相关推荐

    <<JAVA学习笔记>>实例源代码

    本压缩包中包含的"Example"文件夹,极有可能是《JAVA学习笔记》一书中的实例源代码,旨在帮助读者深入理解书中讲解的Java编程原理和实践技巧。下面我们将对这些源代码进行详细解读,以便更好地掌握Java编程。 1. **...

    Java并发编程学习笔记 pdf 多线程编程

    Java并发编程学习笔记,研究JAVA并发多线程编程的一本教程,使用并发技术可以开发出并行算法,充分利用多处理器的计算能力,避免硬件资源浪费。目前,在JAVA并发编程方面的论述系统且内容详实的技术资料不太多,Java...

    Java并发编程学习笔记.rar

    这本"Java并发编程学习笔记"可能是作者在深入研究Java并发特性、工具和最佳实践过程中积累的心得体会。下面,我们将根据这个主题,探讨一些关键的Java并发编程知识点。 1. **线程与进程**:在多任务环境中,线程是...

    java多线程并发编程知识导图笔记.xmind

    java多线程并发编程知识导图笔记.xmind

    Java并发编程学习笔记

    Java并发编程是Java开发中必不可少的一部分,涉及到多线程、同步机制、线程池以及并发工具类等多个核心知识点。以下是对这些主题的详细说明: 1. **线程安全与锁 Synchronized 底层实现原理**: 线程安全是指在多...

    JAVA 多线程学习笔记

    在Java编程中,多线程是一项关键技能,它允许程序...通过深入学习和实践这些知识点,我们可以更好地理解和掌握Java多线程编程,提升程序的并发性能。结合源码分析和实际工具的使用,将使我们成为Java多线程领域的专家。

    java并发编程实践笔记

    2. **确保正确性优先于性能:** 多线程编程中,首先确保程序逻辑的正确性,然后再考虑如何优化性能。 3. **无状态或只读对象是线程安全的:** 如果一个对象不包含任何状态信息(即无状态)或其状态不会改变(只读)...

    java并发编程实践pdf笔记

    Java并发编程实践是Java开发中不可或缺的一个领域,它涉及到如何高效、正确地处理多线程环境中的任务。这本书的读书笔记涵盖了多个关键知识点,旨在帮助读者深入理解Java并发编程的核心概念。 1. **线程和进程的...

    java并发编程学习笔记

    ### Java并发编程学习笔记知识点详解 #### 一、Java并发编程概述 Java并发编程是指在Java应用程序中同时执行多个操作的技术。它通过多线程、线程池等机制实现资源的有效利用,提高程序运行效率。Java并发编程的...

    java编程思想读书笔记

    ### Java编程思想读书笔记 #### 一、Java与C++的区别及内存管理 在学习Java的过程中,我们常常会拿它与C++进行比较。这两门语言虽然有着相似之处,但也有许多不同点。 1. **内存管理:** - C++提供了更为底层的...

    java学习笔记2(多线程)

    java学习笔记2(多线程)java学习笔记2(多线程)

    Java分布式应用学习笔记05多线程下的并发同步器

    ### Java分布式应用学习笔记05多线程下的并发同步器 #### 1. 前言 在现代软件开发中,特别是在分布式系统和高性能计算领域,有效地管理多线程之间的协同工作至关重要。Java语言提供了丰富的工具和API来帮助开发者...

    Java编程思想学习笔记

    在讨论Java编程思想学习笔记时,首先需要了解的是Java语言的平台无关性,而这一特性正是通过Java虚拟机(JVM)得以实现的。JVM作为Java程序设计的关键组成部分,对于Java开发人员来说是必须掌握的基础知识。在该学习...

    Java并发编程笔记

    ### Java并发编程知识点详解 #### 一、线程状态与管理 在Java中,线程具有多种状态,这些状态的变化反映了线程在其生命周期中的不同阶段。理解这些状态及其转换对于编写高效、健壮的并发程序至关重要。 - **NEW**...

    多线程学习笔记

    GCD的使用更为简单和面向对象,它的目的是简化多线程编程,使得开发者能够更加方便地实现并发执行。 GCD中执行任务的两个常用函数是dispatch_sync和dispatch_async。dispatch_sync函数用于同步执行任务,它将任务...

    汪文君高并发编程实战视频资源下载.txt

    │ 高并发编程第二阶段21讲、多线程Future设计模式详细介绍-上.mp4 │ 高并发编程第二阶段22讲、多线程Future设计模式详细介绍-下.mp4 │ 高并发编程第二阶段23讲、第二阶段课程答疑学员问题.mp4 │ 高并发编程...

Global site tag (gtag.js) - Google Analytics