Java多线程的使用

多线程的使⽤

Thread

1
2
3
4
5
6
7
8
Thread thread = new Thread() {
@Override
public void run() {
super.run();
System.out.println("Thread started!");
}
};
thread.start();

       “super.run();”代码可有可无。它表示如果传入了 Runnable(类似下面的 Runnable 方法),就运行 Runnable。

       “thread.start();”方法中会调用 start0() 方法,这是一个 native 方法,java 本身是没有切换线程的能力的,必须让虚拟机指挥操作系统。

Runnable

1
2
3
4
5
6
7
8
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Thread with Runnable started!");
}
};
Thread thread = new Thread(runnable);
thread.start();

       Runnable 和 Thread 使用性能没有区别,选哪个都一样。如果一段代码可以重用,那么写到 Runnable 里面,可以传给多个线程。事实上这两种方法在代码中使用的都不多。

ThreadFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ThreadFactory factory = new ThreadFactory() {
AtomicInteger count = new AtomicInteger(0);
// int count = 0;

@Override
public Thread newThread(Runnable r) {
// count++;
return new Thread(r, "Thread-" + count.incrementAndGet());
}
};

Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " started!");
}
};

Thread thread = factory.newThread(runnable);
thread.start();
Thread thread1 = factory.newThread(runnable);
thread1.start();

       线程工厂,设计模式的一种,工厂方法。

Executor 和线程池

1
2
3
4
5
6
7
8
9
10
11
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Thread with Runnable started!");
}
};

Executor executor = Executors.newCachedThreadPool();
executor.execute(runnable);
executor.execute(runnable);
executor.execute(runnable);

       最常用的一种使用多线程方法,常⽤:newCachedThreadPool() ,该方法返回一个 ExecutorService,ExecutorService 是接口 Executor 的子接口。其中的 shutdown() 方法是一个保守的结束,如果当前没有任何线程执行,Executor 结束并且不再接收新的任务;如果现在有正在执行或者是排队的任务,则等这些人物都执行完毕再结束,并且这个时候不允许有新的排队。shutdownNow() 则直接结束,如果现在有在执行的任务,则直接杀死。

       短时批量处理:newFixedThreadPool()

1
2
3
4
5
6
//bitmap 是 Android 中提供的
ExecutorService executor = Executors.newFixedThreadPool(20);
for(Bitmap bitmap :bitmaps){
executor.execute(bitmapProcessor(bitmap));
}
executor.shutdown();

       线程池分类详见 Android 中的线程池

Callable 和 Future

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Callable<String> callable = new Callable<String>() {
@Override
public String call() {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Done!";
}
};

ExecutorService executor = Executors.newCachedThreadPool();
Future<String> future = executor.submit(callable);
try {
String result = future.get();
System.out.println("result: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}

       Callable 相当于有返回值的 Runnable。future.get(); 方法中,“get()”是一个阻塞的方法,,可以在该方法之前做判断:

1
future.isDone();

       这个方法是瞬间返回的。Callable规定的方法是call(),而Runnable规定的方法是run();Callable任务执行后可返回值,而Runnable的任务是不能返回值的;call()方法可抛出异常,而run()方法是不能抛出异常的;运行Callable任务可拿到一个Future对象。

参考资料:
腾讯课堂 HenCoder
骑小猪看流星 必须要理清的Java线程池

Fork me on GitHub