1.继承Thread类
public class Thread implements Runnable {
方法一:创建一个类继承自Thread类,然后重写run()方法
public class Thread02 {
public static class ThreadDemo extends Thread{
public ThreadDemo(String name){
//编写子类的构造方法
this.setName(name);
}
@Override
public void run() {
//编写自己的线程代码
System.out.println(Thread.currentThread().getName()+"执行");
}
}
public static void main(String[] args) {
ThreadDemo threadDemo = new ThreadDemo("threaddemo");
threadDemo.start();
System.out.println(Thread.currentThread().toString()+"zhixingwangbi");
}
}
方法二:使用lambda表达式
public class thread {
public static int ans=0;
public static void main(String[] args) throws Exception{
Thread[] threads = new Thread[100];
ReentrantLock lock = new ReentrantLock();
for(int i=0;i<100;i++){
//threads[i] =
new Thread(()->{
//lock.lock();
for(int j=0;j<100;j++){
ans++;
System.out.println(ans);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//lock.unlock();
}).start();
}
for(Thread t:threads) t.start();
for(Thread t:threads) t.join();
Thread.sleep(50);
System.out.println("ans="+ans);
}
}
2.实现Runnable接口:run方法
public interface Runnable{
//被线程执行,没有返回值也无法抛出异常
public abstract void run();
}
3.实现Callable接口
3.1Futrue、Callable、Runnable、FutureTask的继承关系
public class FutureTask<V> implements RunnableFuture<V> {
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
public interface Future<V> {
Callable接口
是一个函数式接口,类泛型参数类型与返回值类型一致,call方法相当于Runnable的run()方法,用来写线程的执行任务。
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
Future接口
Callable接口知识单纯地去获得返回值,但是什么时候获取,或者查看线程的运行状态,就需要借助Future。
Future提供了取消任务、获取任务执行的状态与获取结果的能力。
Future源码:
public interface Future<V> {
//取消任务的执行,任务已经完成或者已经被取消时,调用此方法,会返回false
boolean cancel(boolean mayInterruptIfRunning);
//判断任务是否被取消
boolean isCancelled();
//判断任务是否完成(正常完成、异常以及被取消,都将返回true)
boolean isDone();
//阻塞地获取任务执行的结果
V get() throws InterruptedException, ExecutionException;
//在一定时间内,阻塞地获取任务执行的结果
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
RunnableFuture接口
从名字上能看出来,Runnable集成了Runnable与Future接口,run方法来自Runnable接口
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
以上说的,Runnable、Callable、Future以及RunnableFuture都是接口,真正干活还得靠FutureTask
FutureTask类
FutureTask详解:https://blog.csdn.net/qq_39654841/article/details/90631795
FutureTask实现了RunnableFuture接口,RunnableFuture继承了Runnable与Future接口,因此FutureTask既可以作为一个Runnable被Thread执行,也可以获取到Future异步计算的结果。
从上面类图可以看到,传入一个Callable类型的参数可以创建FutureTask对象
下面这个例子,使用构造出来的FutrueTask对象,传入Thread的构造函数中,调用start方法以启动线程。**
FutureTask类的run()是怎么执行的?
源码:可看出,run方法调用了传入的Callable的Call()方法
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();//调用了传入的Callable的Call()方法
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
使用FutureTask和Callable创建线程的小例子
FutureTask有两个构造方法:
构造方法一:传入callable接口
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
构造方法二:传入Runnable和result
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
构造方法一小例子1:
public class CallableFuture02 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//FutureTask接收一个Callable实现类
FutureTask<Integer> futureTask = new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("执行线程");
return 200;//返回结果
}
});
//FutureTask实现了Runnable接口,用Runnable创建一个线程
//注意这里,这里传入futureTask参数,构造了一个Thread,因为Thread只有种构造方式,一种是直接实例化,一种是使用Runnable接口实例化,没有第三种方法,这里是因为FutureTask继承了Runnable接口
new Thread(futureTask).start();//开启线程
int result = futureTask.get();//获取线程的最终结果
System.out.println("main come over");
}
}
构造方法一小例子2:(不用看)
public class CallableFuture01 {
static class Task implements Callable<Integer> {
@Override
public Integer call() throws Exception {
//模拟任务耗时
Thread.sleep(2000);
return 1;
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
//FutureTask接收一个Callable实现类
FutureTask<Integer> futureTask = new FutureTask<>(new Task());
//FutureTask实现了RunnableFuture,间接实现了Runnable接口,因此可作为参数传给Thread的构造方法中
new Thread(futureTask).start();
//get()方法会阻塞2秒,输出1
int result = futureTask.get();
System.out.println(result);
}
}
构造方法一小例子3:(不用看)
匿名内部类
public class CallableFuture01 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//FutureTask接收一个Callable实现类
//使用了匿名内部类
FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+"执行了");
return 300;
}
});
//FutureTask实现了RunnableFuture,间接实现了Runnable接口,因此可作为参数传给Thread的构造方法中
new Thread(futureTask).start();
//get()方法会阻塞2秒,输出1
int result = futureTask.get();
System.out.println(result);
}
}
也可以使用Lambda表达式,对于接口中只有一个需要实现的抽象方法时,可以使用Lambda表达式
public interface Callable<V>{
//计算结果、或无法这样做时抛出异常
//@return 计算得到的结果
//@throws 如果无法计算结果,则抛出异常
V call() throws Exception;
}
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}
FutureTask简介
FutureTask有三种状态:
4.线程池方式
线程池方式详解见:
ThreadPoolExecutor
public void execute(Runnable command)
public class ThreadPool01 {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(5,10,100, TimeUnit.SECONDS,new ArrayBlockingQueue<>(100),new ThreadPoolExecutor.AbortPolicy());
for(int i=0;i<10;i++){
executor.execute(()->{
System.out.println("线程"+2+"is running");
});
//executor.execute();
}
//终止线程池
executor.shutdown();
while(!executor.isTerminated()){}
System.out.println("main come over");
}
}
线程池方式使用Callable
public class ThreadPool01 {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(5,10,100, TimeUnit.SECONDS,new ArrayBlockingQueue<>(100),new ThreadPoolExecutor.AbortPolicy());
for(int i=0;i<10;i++){
FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+"执行了");
return 300;
}
});
executor.execute(futureTask);
}
//终止线程池
executor.shutdown();
while(!executor.isTerminated()){}
System.out.println("main come over");
}
}
4.1. 线程池的 execute()方法和 submit()方法的区别是什么呢?
(1)execute()方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功与否;
public interface Executor {
void execute(Runnable command);
}
(2)submit()方法用于提交需要返回值的任务。线程池会返回一个 Future 类型的对象,通过这个 Future 对象可以判断任务是否执行成功,并且可以通过 Future 的 get()方法来获取返回值,get()方法会阻塞当前线程直到任务完成,而使用 get(long timeout,TimeUnit unit)方法则会阻塞当前线程一段时间后立即返回,这时候有可能任务没有执行完。
我们以 AbstractExecutorService 接口 中的一个 submit 方法为例子来看看源代码:
public interface ExecutorService extends Executor {
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
}
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
上面方法调用的 newTaskFor 方法返回了一个 FutureTask 对象。
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FutureTask<T>(runnable, value);
}
我们再来看看execute()方法:
public void execute(Runnable command) {
...
}