Java多线程艺术
Thread方式
具体步骤
- 定义Thread类的子类,并重写该类的run方法,该run方法的方法体就是代表了线程需要完成的任务。因此,我们经常把run方法称为线程执行体。
- 创建Thread子类的实例,即使创建了线程对象。
- 用线程对象的start方法来启动该线程。
public class Driver {
// 创建MyThread类
// 从Thread 派生
public static class MyThread extends Thread {
// 重写run()方法
public void run() {
System.out.println("使用多线程的第一种方式");
}
}
public static void main(String[] args) {
// 第一种方法
// 创建MyThread 实例
MyThread thread = new MyThread();
// 调用start() 启动线程
thread.start();
// 第一种方法
// 创建MyThread 实例
System.out.println("main start......");
Thread thread01 = new MyThread(){
public void run(){
System.out.println("thread run.....");
System.out.println("thread end.....");
}
};
thread01.start();
System.out.println("main end......");
System.out.println("*************************************");
}
}
Runnable方式
详细操作步骤
- 定义Runnable接口的实现类,并重写该接口的run方法,该run方法的方法体同样是该线程的线程执行体。
- 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
- 调用线程对象的start方法来启动该线程。
public class Driver {
//如果一个类已经从某个类派生,无法从Thread继承:
//实现Runnable接口
public static class MyThread2 implements Runnable {
// 覆写/重写run()方法
@Override
public void run() {
System.out.println("使用多线程的第二种方式");
}
}
public static void main(String[] args) {
// 第二种方法
// 在main()方法中创建Runnable实例
System.out.println("main start ......");
Runnable runnable = new MyThread2();
// 创建Thread实例并传入Runnable
MyThread thread1 = new Thread(runnable);
// 调用start()启动线程
thread1.start();
System.out.println("main end......");
}
}
Callable 方式
代码实现步骤
- 创建Calable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,且该call方法有返回值。
注意事项:Callable接口有泛型限制,Callable接口里的泛型形参类型与call方法返回值类型相同。
- 创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象call()方法的返回值。
- 使用FutureTask对象作为Thread对象的target创建、并启动新线程。
- 调用FutureTask对象的方法来获得子线程执行结束后的返回值。
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class Driver {
public static class CallableThread implements Callable<Integer> {
// 实现call方法,作为线程执行体
@Override
public Integer call() throws Exception {
int i = 0;
for (; i < 1000; i++) {
System.out.println(Thread.currentThread().getName() + "\t的循环变量i的值:\t" + i);
}
// call(方法可以有返回值)
return i;
}
}
public static void main(String[] args) {
// 创建Callable 对象
CallableThread callableThread = new CallableThread();
// 使用FutureTask来包装Callable 对象
FutureTask<Integer> futureTask = new FutureTask<Integer>(callableThread);
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "\t的循环变量i的值:\t" + i);
if (i == 20) {
// 实质还是以Callable对象来创建,并启动线程
new Thread(futureTask, "有返回值的线程").start();
}
}
try {
// 获取线程返回值
System.out.println("子线程的返回值:\t" + futureTask.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
线程池
- 调用Executors类的静态工厂方法创建一个ExecutorService对象,该对象代表一个线程池。
- 创建Runnable实现类或Callable实现类的实例,作为线程执行任务。
- 调用ExecutorService对象的submit 方法来提交Runnable实例或Callable实例。
- 当不想提交任何任务时调用ExecutorService对象的shutdown方法来关闭线程池。
import java.util.concurrent.*;
public class Driver {
/**
* 第二步 创建Runnable实现类或者Callable实现类的实例,作为线程执行任务
*/
public static class ThreadPool implements Runnable {
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
System.out.println(Thread.currentThread().getName()+"的i值为:\t"+i);
}
}
}
public static void main(String[] args) {
/**
* 第一步 调用Executors类的静态工厂方法创建一个ExecutorService对象,该对象代表一个线程池。
* */
// 创建一个具有固定线程数(6)的线程池
ExecutorService pool= Executors.newFixedThreadPool(6);
/**
* 第三步 调用ExecutorService对象的submit方法来提交Runnable实例或者Callable 实例
*/
// 向线程池中提交两个线程
pool.submit(new ThreadPool());
pool.submit(new ThreadPool());
/**
* 第四步 当不想提交任何任务时 调用ExecutorService对象的shutdown方法来关闭线程池
*/
// 关闭线程池
pool.shutdown();
}
}
例子01
//创建一个类,实现Runnable接口,重写run方法,设置线程任务
public class RunnableImpl implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"创建一个新的线程执行");
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 线程池的使用步骤:
*
* 1.使用线程池的工厂类Executors里边提供的静态方法newFixedTmreodPool生产一个指定线程数量的练程池
*
* 2.创建一个类,实现Runnable接口,重写run方法,设置线程任务
*
* 3.调用ExecutorService中的方法submit,传递线程任务(实现类),开启线程,执行run方法
*
* 4.调用ExecutorService中的方法shutdown销毁线程池(一般不推荐使用)
*/
public class Driver {
public static void main(String[] args) {
// 1.使用线程池的工厂类Executors里边提供的静态方法newFixedTmreodPool生产一个指定线程数量的练程池
ExecutorService executorService= Executors.newFixedThreadPool(3);
// * 2.创建一个类,实现Runnable接口,重写run方法,设置线程任务
// * 3.调用ExecutorService中的方法submit,传递线程任务(实现类),开启线程,执行run方法
for (int i = 0; i <15 ; i++) {
// 线程池会一直开启,使用完了线程,会自动把线程归还给线程池,线程可以继续使用
executorService.submit(new RunnableImpl());
}
}
}
例子02
public class HandleRunnable implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
import java.util.concurrent.*;
public class Driver {
public static void main(String[] args) {
//第一部分 创建单线程的线程池
// 创建单线程的线程池
// ExecutorService executorService=Executors.newSingleThreadExecutor();
//第二部分 创建固定数量的线程池
/* * 创建具一个可重用的,有固定数量的线程池
* * 每次提交一个任务就提交一个线程,直到线程达到线城池大小,就不会创建新线程了
* * 线程池的大小达到最大后达到稳定不变,如果一个线程异常终止,则会创建新的线程
* */
// ExecutorService executorService=Executors.newFixedThreadPool(10);
//第三部分 创建数量不固定的线程池
/**
* /* * 具有缓冲功能的线程池,系统根据需要创建线程,线程会被缓冲到线程池中
* * 如果线程池大小超过了处理任务所需要的线程线程池就会回收空闲的线程池,
* * 当处理任务增加时,线程池可以增加线程来处理任务线程池不会对线程的大
* * 小进行限制线程池的大小依赖于操作系统 */
/* ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 1000; i++) {
HandleRunnable handleRunnable = new HandleRunnable();
executorService.execute(handleRunnable);
}
executorService.shutdown(); */
// 第四部分 创建定时线程池
/* * 创建一个线程池,大小可以设置,此线程支持定时以及周期性的执行任务定时任务 */
for (int i = 0; i < 1000; i++) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
HandleRunnable handleRunnable = new HandleRunnable();
//参数1:目标对象 参数2:隔多长时间开始执行线程, 参数3:执行周期 参数4:时间单位
scheduledExecutorService.scheduleAtFixedRate(handleRunnable, 3, 1, TimeUnit.MICROSECONDS);
}
}
}
posted on 2019-04-05 17:52 Indian_Mysore 阅读(234) 评论(6) 编辑 收藏 举报