继承Thread类
定义一个类继承Thread类,重写父类的run()方法
/**
* 定义一个类继承Thread类
* 重写父类的run方法(需要该线程执行的代码块)
*/
public class MyThread extends Thread{
public MyThread() {}
@Override
public void run() {
for(int i = 0; i<100; i++){
System.out.println(i);
}
}
}
测试类
/**
* 创建自定义线程类MyThread的实例
* 1.为什么要重写run()方法
* ---因为run()是用来封装被线程执行的代码
* 2.run()与start()的区别
* ---run():封装线程执行的代码,直接调用相当于普通方法的调用
* ---start():启动线程;由jvm调用此线程的run()方法
*/
public class MyThreadTest {
public static void main(String[] args) {
MyThread my1 = new MyThread();
MyThread my2 = new MyThread();
// 通过start()方法执行
my1.start();
my2.start();
}
}
实现Runnalbe接口
定义一个类实现Runnable接口
/**
* 实现Runnable接口也可以实现多线程
*/
public class MyRunnable implements Runnable{
public MyRunnable(){}
@Override
public void run() {
for(int i=0; i<100; i++){
System.out.println(i);
}
}
}
测试类
public class MyRunnableTest {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
// 创建Thread类的对象,实现Runnable接口的类的实例作为构造方法的参数
Thread thread1 = new Thread(myRunnable, "高铁");
Thread thread2 = new Thread(myRunnable, "飞机");
thread1.start();
thread2.start();
// lambda表达式简洁写法
Thread thread4 = new Thread(()->{
for(int i=0; i<100; i++){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}, "轿车");
thread4.start();
}
}
实现Callable接口
这里线程任务是计算0到n-1的和
/**
* 实现callable<T>接口,结合FutureTask完成
*/
public class MyCallable implements Callable<String> {
private int n;
public MyCallable(int n){
this.n = n;
}
@Override
public String call() throws Exception {
int sum = 0;
for(int i=0; i<n; i++){
sum += i;
}
return String.valueOf(sum);
}
}
测试类
Thread类的构造器不支持Callable接口的实例,支持Runnable接口的实例
但FutureTask对象继承了RunnableFuture接口,而RunnableFurure接口继承了Runnable接口(多态)
FutureTask对象的get()方法可以等线程执行完毕后得到线程执行的结果
Callable对象任务交给FutureTask对象实现
public class MyCallableTest {
public static void main(String[] args) {
MyCallable myCallable1 = new MyCallable(10000);
MyCallable myCallable2 = new MyCallable(15000);
FutureTask<String> f1 = new FutureTask<>(myCallable1);
FutureTask<String> f2 = new FutureTask<>(myCallable2);
Thread thread1 = new Thread(f1);
Thread thread2 = new Thread(f2);
thread1.start();
thread2.start();
// 如果f1任务没有完成,这里代码会等待,直到线程1跑完才提取结果
try {
String r1 = f1.get();
System.out.println(r1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
System.out.println("-------------------");
try {
String r2 = f2.get();
System.out.println(r2);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}
}
线程池--Runnable接口任务
先写好线程任务
public class RunnableTask implements Runnable{
@Override
public void run() {
for(int i=0; i<1; i++){
System.out.println(Thread.currentThread().getName() + " hello");
}
}
}
调用线程池的execute方法实现Runnable接口任务
/**
* 线程池的参数介绍
* public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUint unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
* corePoolSize: 指定线程池的线程数量(核心线程) 不能小于0
* maximumPoolSize: 指定线程池最大线程数 最大数量 >= 核心线程数量
* keepAliveTime: 指定临时线程的最大存活时间 不能小于0
* unit: 指定存活时间的单位(秒、分、时、天) 时间单位
* workQueue: 指定任务队列 不能为null
* threadFactory: 指定用哪个线程工厂创建线程 不能为null
* handler: 指定线程忙,任务满的时候,新任务来了怎么办 不能为null
*/
/**
* ThreadPoolExecutor.AbortPolicy 丢弃任务并抛出RejectedExecutionException异常。
是默认的策略
* ThreadPoolExecutor.DiscardPolicy 丢弃任务,但是不抛出异常,这是不推荐的做法
* ThreadPoolExecutor.DiscardOldestPolicy 抛弃队列中等待最久的任务,然后把当前任务加入队列中
* ThreadPoolExecutor.CallerRunsPolicy 由主线程负责调用任务的run()方法从而绕过线程池直接执行
*/
/**
* 临时线程什么时候创建
* 新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程
* 什么时候会开始拒绝任务
* 核心线程和临时线程都在忙,任务队列也满了,新的任务过来时才会开始拒绝
*/
/**
* 自定义一个线程池对象,并测试其特性,处理Runnable任务
*/
public class RunnableTest {
public static void main(String[] args) {
ExecutorService pool = new ThreadPoolExecutor(3, 5, 6, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(5),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
// 给任务线程池处理
Runnable target = new RunnableTask();
// 核心线程3个
pool.execute(target);
pool.execute(target);
pool.execute(target);
// 任务队列5个
pool.execute(target);
pool.execute(target);
pool.execute(target);
pool.execute(target);
pool.execute(target);
// 再加任务创建临时线程,最多2个
pool.execute(target);
pool.execute(target);
// 线程池和临时队列都满了,不创建,抛出异常,
// pool.execute(target);
//
// pool.shutdownNow(); // 立即关闭,即使任务没完成,会丢失任务
// pool.shutdown(); // 会等待全部任务执行完毕后再关闭
}
}
线程池--Callable任务
先写好线程任务
public class CallableTask implements Callable<String> {
private int n;
public CallableTask(int n){
this.n = n;
}
@Override
public String call() throws Exception {
int sum = 0;
for(int i=0; i<n; i++){
sum += i;
}
return Thread.currentThread().getName() + " " + sum;
}
}
调用线程池的submit()方法实现callable<T>接口任务,返回Future<T>对象
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService pool = new ThreadPoolExecutor(3, 5, 6, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
Future<String> f1 = pool.submit(new CallableTask(100));
Future<String> f2 = pool.submit(new CallableTask(1000));
Future<String> f3 = pool.submit(new CallableTask(10000));
Future<String> f4 = pool.submit(new CallableTask(100000));
Future<String> f5 = pool.submit(new CallableTask(1000000));
// 依然是按顺序输出线程执行的值
System.out.println(f1.get());
System.out.println(f2.get());
System.out.println(f3.get());
System.out.println(f4.get());
System.out.println(f5.get());
}
}