`
dasheng
  • 浏览: 146246 次
  • 性别: 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
捕获了异常。

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics