1、Thread 类的join() 方法
当前线程调用某个线程的这个方法时,它会暂停当前线程,直到被调用线程执行完成。
例子:
public class DataSourcesLoader implements Runnable{
@Override
public void run() {
System.out.println(" ---Begin DataSourcesLoader ---" );
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException ex) {
Logger.getLogger(DataSourcesLoader.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(" ---End DataSourcesLoader ---" );
}
public static void main(String[] args)
{
System.out.println(" ---Begin Main ---" );
Thread t = new Thread(new DataSourcesLoader());
t.start();
try {
t.join();
} catch (InterruptedException ex) {
Logger.getLogger(DataSourcesLoader.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(" ---End Main ---" );
}
}
输出为:
run:
---Begin Main ---
---Begin DataSourcesLoader ---
---End DataSourcesLoader ---
---End Main ---
BUILD SUCCESSFUL (total time: 4 seconds)
保证了 在t进程完成之后,main进程再完成。
2、守护线程setDaemon
当守护线程是程序里唯一在运行的线程时,JVM会结束守护线程并终止程序。
只能在start() 方法之前可以调用 setDaemon() 方法。一旦线程运行了,就不能修改守护状态。
可以使用 isDaemon() 方法来检查线程是否是守护线程(方法返回 true) 或者是使用者线程 (方法返回 false)
3、UncaughtExceptionHandler 接口
可以在线程里处理不受控制的异常
public class MyUncaughtExceptionHandler implements UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("Thread:" + t.getId());
System.out.println("Thread status:" + t.getState());
System.out.println("Exception:" + e.getMessage());
System.out.println("Exception Stack Trace: ");
e.printStackTrace(System.out);
}
public static void main(String[] args) {
Thread t = new Thread(new MyTask());
t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
t.start();
}
}
class MyTask implements Runnable {
@Override
public void run() {
System.out.println("----- start MyTask -----");
if (true) {
throw new RuntimeException("HAHAHAHHAHAHA");
}
System.out.println("----- end MyTask -----");
}
}
输出
----- start MyTask -----
Thread:9
Thread status:RUNNABLE
Exception:HAHAHAHHAHAHA
Exception Stack Trace:
java.lang.RuntimeException: HAHAHAHHAHAHA
at chapter1.MyTask.run(MyUncaughtExceptionHandler.java:37)
at java.lang.Thread.run(Thread.java:744)
BUILD SUCCESSFUL (total time: 0 seconds)
4、线程工厂ThreadFactory 生成线程
ThreadFactory 有一个方法: public Thread newThread(Runnable r)
public class MyThreadFactory implements ThreadFactory {
private int counter;
private String name;
private List<String> stats;
public MyThreadFactory(String name) {
counter = 0;
this.name = name;
stats = new ArrayList<String>();
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, name + "-Thread_" + counter);
counter++;
stats.add(String.format("created thread %d with name %s on %s\n", t.getId(), t.getName(), new Date()));
return t;
}
public String getStats() {
StringBuffer buffer = new StringBuffer();
Iterator<String> it = stats.iterator();
while (it.hasNext()) {
buffer.append(it.next());
buffer.append("\n");
}
return buffer.toString();
}
public static void main(String[] args) {
MyThreadFactory factory = new MyThreadFactory("MyThreadFactory");
Task task = new Task();
Thread thread;
System.out.printf("Starting the Threads\n");
for (int i = 0; i < 10; i++) {
thread = factory.newThread(task);
thread.start();
}
System.out.printf("Factory stats:\n");
System.out.printf("%s\n", factory.getStats());
}
}
class Task implements Runnable {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
5、线程中断 interrupt
public class InterruptTest {
public static void main(String[] args) {
Thread task = new PrimeGenerator();
task.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
task.interrupt();
}
}
class PrimeGenerator extends Thread {
@Override
public void run() {
long number = 1L;
while (true) {
if (isPrime(number)) {
System.out.printf("Number %d is Prime", number);
}
if (isInterrupted()) {
System.out.printf("The Prime Generator has been Interrupted");
return;
}
number++;
}
}
private boolean isPrime(long number) {
if (number <= 2) {
return true;
}
for (long i = 2; i < number; i++) {
if ((number % i) == 0) {
return false;
}
}
return true;
}
}
isInterrupted()和interrupted() 方法有着很重要的区别:
第一个不会改变interrupted属性值,但是第二个会设置成false。
interrupted() 方法是一个静态方法,建议使用isInterrupted()方法。
5、线程中断 InterruptException
如果线程实现的是由复杂的算法分成的一些方法,或者它的方法有递归调用,那么我们可以用更好的机制来控制线程中断。为了这个Java提供了InterruptedException异常。当你检测到程序的中断并在run()方法内捕获,你可以抛这个异常。
public class InterruptExceptionTest {
public static void main(String[] args) {
FileSearch searcher = new FileSearch("C:\\", "autoexec.bat");
Thread thread = new Thread(searcher);
thread.start();
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
}
}
class FileSearch implements Runnable {
private String initPath;
private String fileName;
public FileSearch(String initPath, String fileName) {
this.initPath = initPath;
this.fileName = fileName;
}
@Override
public void run() {
File file = new File(initPath);
if (file.isDirectory()) {
try {
directoryProcess(file);
} catch (InterruptedException e) {
System.out.printf("%s: The search has been interrupted", Thread
.currentThread().getName());
}
}
}
private void directoryProcess(File file) throws InterruptedException {
File list[] = file.listFiles();
if (list != null) {
for (int i = 0; i < list.length; i++) {
if (list[i].isDirectory()) {
directoryProcess(list[i]);
} else {
fileProcess(list[i]);
}
}
}
if (Thread.interrupted()) {
throw new InterruptedException();
}
}
private void fileProcess(File file) throws InterruptedException {
if (file.getName().equals(fileName)) {
System.out.printf("%s : %s\n", Thread.currentThread().getName(),
file.getAbsolutePath());
}
if (Thread.interrupted()) {
throw new InterruptedException();
}
}
}