Thread创建线程的两种方法
我们先来看一下Thread源码介绍。
/**There are two ways to create a new thread of execution. One is to
* declare a class to be a subclass of <code>Thread</code>. This
* subclass should override the <code>run</code> method of class
* <code>Thread</code>. An instance of the subclass can then be
* allocated and started. For example, a thread that computes primes
* larger than a stated value could be written as follows:
* <hr><blockquote><pre>
* class PrimeThread extends Thread {
* long minPrime;
* PrimeThread(long minPrime) {
* this.minPrime = minPrime;
* }
*
* public void run() {
* // compute primes larger than minPrime
* . . .
* }
* }
* </pre></blockquote><hr>
* <p>
* The following code would then create a thread and start it running:
* <blockquote><pre>
* PrimeThread p = new PrimeThread(143);
* p.start();
* </pre></blockquote>
* <p>
* The other way to create a thread is to declare a class that
* implements the <code>Runnable</code> interface. That class then
* implements the <code>run</code> method. An instance of the class can
* then be allocated, passed as an argument when creating
* <code>Thread</code>, and started. The same example in this other
* style looks like the following:
* <hr><blockquote><pre>
* class PrimeRun implements Runnable {
* long minPrime;
* PrimeRun(long minPrime) {
* this.minPrime = minPrime;
* }
*
* public void run() {
* // compute primes larger than minPrime
* . . .
* }
* }
* </pre></blockquote><hr>
* <p>
* The following code would then create a thread and start it running:
* <blockquote><pre>
* PrimeRun p = new PrimeRun(143);
* new Thread(p).start();
* </pre></blockquote>
/* <p>
上面介绍了Thread有两种方法来创建一个新的线程。大概讲的就是第一个方法是声明Thread的子类,并覆盖run方法。创建另一种方法即是声明一个类实现Runnable接口,然后类的实例作为Thread类的构造参数注入即可。
public class CreateThread {
public static void main(String[] args) {
// 1Thread子类
CreateTest createTest = new CreateTest();
createTest.start();
// 2实现Runnable接口,构造注入Thread
Thread thread = new Thread(new RunTest());
thread.start();
}
}
class CreateTest extends Thread {
@Override
public void run() {
System.out.println("create thread success:one");
}
}
class RunTest implements Runnable {
@Override
public void run() {
System.out.println("create thread success:two");
}
}
线程的创建并不难,所以不用浪费过多的时间。下面我们来看看线程的几种常用操作。
Thread常用方法
| 返回值 | 方法名 | 注解 |
|---|---|---|
| Thread | currentThread() | 获取当前线程,一般用来获取当前线程一些状态信息 |
| long | getId() | 与currentThread方法协调使用,获取当前线程Id,Id唯一 |
| String | getName()/setName() | 获取当前线程名/修改 |
| int | getPriority()/setPriority() | 获取当前线程优先级/修改 |
| void | interrupt() | 中断当前线程命令 |
| boolean | interrupted() | 检查是否中断 |
| boolean | isAlive() | 检查是否存活 |
| boolean | isDaemon() | 是否是守护线程 |
| void | join() | 等待线程死亡,主线程等待该线程死亡才能执行之后的代码 |
| void | start() | 启动线程 |
| void | run() | 重启线程,注意是重启线程不是新开个线程启动 |
| void | sleep(long millis) | 让出当前的时间片,由其他线程执行。孔融让梨的说法。 |
| void | yield() | 放弃当前的时间片,但是不放弃资源 |
Thread状态简介
| 状态 | 注解 |
|---|---|
| 新建 | new Thread且未启动 |
| 运行 | 创建了并启动了线程 |
| 阻塞 | 该线程在等待锁的释放 |
| 等待 | 等待其他锁的唤醒,常见等待wait()等待其他持有锁的notify()唤醒 |
| 超时等待 | 等待设置时间,时间到了自己重回运行状态 |
| 死亡 | 线程运行结束或者调用相应命令,例如interrupt |
Future 获取线程处理结果
在一些业务场景,需要返回线程的处理结果。Executors线程池提供了相关的接口。Future可定义返回类型。我们来看看源码是怎么解释的。
/**
* A {@code Future} represents the result of an asynchronous
* computation. Methods are provided to check if the computation is
* complete, to wait for its completion, and to retrieve the result of
* the computation. The result can only be retrieved using method
* {@code get} when the computation has completed, blocking if
* necessary until it is ready. Cancellation is performed by the
* {@code cancel} method. Additional methods are provided to
* determine if the task completed normally or was cancelled. Once a
* computation has completed, the computation cannot be cancelled.
* If you would like to use a {@code Future} for the sake
* of cancellability but not provide a usable result, you can
* declare types of the form {@code Future<?>} and
* return {@code null} as a result of the underlying task.
*
* <p>
* <b>Sample Usage</b> (Note that the following classes are all
* made-up.)
* <pre> {@code
* interface ArchiveSearcher { String search(String target); }
* class App {
* ExecutorService executor = ...
* ArchiveSearcher searcher = ...
* void showSearch(final String target)
* throws InterruptedException {
* Future<String> future
* = executor.submit(new Callable<String>() {
* public String call() {
* return searcher.search(target);
* }});
* displayOtherThings(); // do other things while searching
* try {
* displayText(future.get()); // use future
* } catch (ExecutionException ex) { cleanup(); return; }
* }
* }}</pre>
*/
源码的解释就是Future标识异步的结果计算,用于检查计算是否正确。可用get方法获取结果。cancel方法确认任务是否正常完成是否被取消。Future可以自定义声明返回类型作为结果返回。下面我们来实现一下这个异步获取结果的Future。
public class CreateFuture{
public static int num;
public static void main(String[] args) throws Exception{
System.out.println("init :" + CreateFuture.num);
// Future由线程池提供,所以先创建线程池
ExecutorService service = Executors.newCachedThreadPool();
// 同等于Thread的Runnable
Task task = new Task();
// 接收返回数据 用get获取
Future<Integer> result = service.submit(task);
System.out.println("future + callable: " + result.get());
// FutureTask与Future实现基本相同 事先定义好返回类型
FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
service.submit(futureTask);
System.out.println("futuretask + callable: " + futureTask.get());
service.shutdown();
}
}
// 该实现接口方法与Thread实现线程的Runnable异曲同工
// 可自声明返回类型
class Task implements Callable<Integer>{
@Override
public Integer call() throws Exception {
return ++CreateFuture.num;
}
}
以上就是线程的一些基本信息,如有错误或者不足的地方欢迎指正。