线程的创建,操作与其他状态查询

281 阅读5分钟

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
 *             &nbsp;.&nbsp;.&nbsp;.
 *         }
 *     }
 * </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
 *             &nbsp;.&nbsp;.&nbsp;.
 *         }
 *     }
 * </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;
   }
}

以上就是线程的一些基本信息,如有错误或者不足的地方欢迎指正。

源码下载地址