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
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
new ArrayList
results.add(exec.submit(new TaskWithResult(i)));
for(Future
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
捕获了异常。