java线程之isAlive方法,sleep方法,和getId方法

本文深入解析Java线程中的isAlive方法、sleep方法及getId方法,通过实例演示这些方法的应用场景及注意事项。

java线程之isAlive方法,sleep方法,和getId方法


  • isAlive方法
  • sleep方法
  • getId方法

提示
博主:章飞_906285288
博客地址: http://blog.csdn.net/qq_29924041

isAlive方法

isAlive方法,即线程的活动情况,参考一下前面线程中讲到的,线程的几种状态。有一个就绪和运行状态,指的就是Alive状态。
所以活动状态其实就是线程已经启动了,并且没有停止的这个中间过程状态
源码:

 /**
     * Tests if this thread is alive. A thread is alive if it has
     * been started and has not yet died.
     *
     * @return  <code>true</code> if this thread is alive;
     *          <code>false</code> otherwise.
     */
    public final native boolean isAlive();

从上面的解释其实也可以看到,线程start了,并且没有died的中间状态

在测试这个状态的时候需要注意的是,是否是你对应的当前线程的活跃度的情况,参考之前的this,和currentThread。


sleep方法

sleep方法其实很简单,如果在java中应用的话,其实没有太多弯弯绕绕的,但是如果在android中的话,就需要注意了,注意当前的运行环境是否是主线程。因为线程只有在start启动后,才算是一个异步过程,如果仅仅只是run了一下,其实还是同步过程,在主线程中,对比的话,也同样是需要参考this,和currentThread的
简单low一下源码:

/**
     * Causes the currently executing thread to sleep (temporarily cease
     * execution) for the specified number of milliseconds, subject to
     * the precision and accuracy of system timers and schedulers. The thread
     * does not lose ownership of any monitors.
     *
     * @param  millis
     *         the length of time to sleep in milliseconds
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public static native void sleep(long millis) throws InterruptedException;

它的解释是,会导致当前执行代码块的线程进行一段时间的休眠。
其实在线程中的休眠有两个方法,一个方法是sleep过程,另外一个就是wait的过程。需要做个简单的区分,因为sleep是在执行过程的内部进行休眠,如果其持有锁的话,是不会去释放锁不会释放资源的,但是wait不一样,wait可以理解为等待的意思,这个时候它会把锁给释放。


getId方法

getId顾名思义,其实就是获取线程ID的意思,同时还有一个getName的方法,做个简单的区分,每个线程在生成的时候都是有唯一一个固定的ID的,但是对应的Name是通过set方法设置,或者线程按照自己的编号进行默认生成的过程,这就导致的。其实Name是可以重复的。而ID则不允许重复

源码:
获取线程ID的源码部分

 /**
     * Returns the identifier of this Thread.  The thread ID is a positive
     * <tt>long</tt> number generated when this thread was created.
     * The thread ID is unique and remains unchanged during its lifetime.
     * When a thread is terminated, this thread ID may be reused.
     *
     * @return this thread's ID.
     * @since 1.5
     */
    public long getId() {
        return tid;
    }
 /*
     * Thread ID
     */
    private long tid;

通过threadSeqNumber自增来进行编排的

 /* Set thread ID */
 tid = nextThreadID();
 private static synchronized long nextThreadID() {
        return ++threadSeqNumber;
    }

一小段测试代码:

package com.zzf.java.charpter1.part10;

import java.util.Date;

/**
 * 线程的构造函数在别的线程中被调用,这个时候当前调用的线程的ID为1
 * 注意区分的概念就是:当前线程和当前调用的线程。
 * isAlive
 * isAlive描述的是线程的活跃度。即活动状态,这种状态指的是已经start启动并且没有终止的状态
 * this.isAlive是当前进程的活跃情况,在这里当然指的就是当前对象,因为线程没有start起来,所以isAlive是false,而由于此段代码是在主线程中去调用,所以主线程的活跃状态为true
 * 
 * getId
 * Id才是线程的唯一标示,因为Name是可以重名的,但是Id是不会重名的
 * 
 * sleep方法
 * sleep一般指的是线程的休眠时间,因为已经区分过了,只有在start启动,或者run被别的线程调用的时候,这个时候才会有在子线程中睡眠这一说,如果在主线程中去调用的话,导致主线程睡眠,
 * 在子线程中调用的话,这个是不会影响主线程的
 * 
 * @author zhouzhangfei
 *
 */
public class MyThread10 extends Thread{
    public MyThread10() {
        // TODO Auto-generated constructor stub
        System.out.println("this.getName:"+this.getName()+"\t"+"currentThread.getName:"+Thread.currentThread().getName());
        System.out.println("this.getId:"+this.getId()+"\t"+"currentThread.getId:"+Thread.currentThread().getId());
        System.out.println("this.isAlive:"+this.isAlive()+"\tcurrentThread.isAlived:"+currentThread().isAlive());

        System.out.println("beforesleep:"+System.currentTimeMillis());
        try {
            //主线程中去睡眠了2000ms
            sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("aftersleep:"+System.currentTimeMillis());
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        System.out.println("run:\t"+"this.isAlive:"+this.isAlive()+"\tcurrentThread.isAlived:"+Thread.currentThread().isAlive()+"\tcurrentThread.getName:"+
        Thread.currentThread().getName()+"\tgetId:"+Thread.currentThread().getId());
        System.out.println("run\tbeforesleep:"+System.currentTimeMillis()+"\tcurrentThreadId:"+Thread.currentThread().getId());
        try {
            sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("run\taftersleep:"+System.currentTimeMillis()+"\tcurrentThreadId:"+Thread.currentThread().getId());
    }
}
package com.zzf.java.charpter1.part10;

public class Part10Main {
    public static void main(String[] args) {
        MyThread10 myThread10 = new MyThread10();

        Thread mtThread = new Thread(myThread10);
        mtThread.setName("ABC");
        mtThread.start();   
        myThread10.start();

        Thread mtThread2 = new Thread(myThread10);
        mtThread2.setName("ABC");
        mtThread2.start();
    }
}

输出的结果为:

this.getName:Thread-0   currentThread.getName:main
this.getId:9    currentThread.getId:1
this.isAlive:false  currentThread.isAlived:true
beforesleep:1516756915153
aftersleep:1516756917158
run:    this.isAlive:true   currentThread.isAlived:true currentThread.getName:ABC   getId:10
run:    this.isAlive:true   currentThread.isAlived:true currentThread.getName:Thread-0  getId:9
run beforesleep:1516756917159   currentThreadId:9
run beforesleep:1516756917159   currentThreadId:10
run:    this.isAlive:true   currentThread.isAlived:true currentThread.getName:ABC   getId:11
run beforesleep:1516756917159   currentThreadId:11
run aftersleep:1516756919163    currentThreadId:10
run aftersleep:1516756919163    currentThreadId:9
run aftersleep:1516756919163    currentThreadId:11

以上就是针对isAlive,sleep和getId简单的一些分析

<think>我们参考用户提供的引用之前的回答,用户需要的是在Java中开启线程执行查询方法的具体代码示例。查询方法通常指数据库查询、文件读取等耗时操作,为避免阻塞主线程,需要异步执行。 根据引用[1][2],我们可以使用Thread类、Runnable接口或线程池(引用[3])来实现。同时,引用[4]提到了BIO模型中使用线程池处理连接,这也可以作为参考。 由于查询操作可能需要返回结果,因此我们考虑两种方式: 1. 使用Runnable配合共享变量(或回调)获取结果(但需注意线程同步) 2. 使用CallableFuture(通过线程池)获取结果(更推荐) 下面我们提供两种实现方式: ### 方式1:使用Runnable接口(配合回调) 这种方式适用于不需要立即获取结果,或者通过回调函数处理结果的场景。 ```java import java.util.concurrent.*; public class QueryWithRunnable { // 定义回调接口 public interface QueryCallback { void onResult(String result); void onError(Exception e); } // 查询任务(使用回调返回结果) static class QueryTask implements Runnable { private final QueryCallback callback; public QueryTask(QueryCallback callback) { this.callback = callback; } @Override public void run() { try { // 模拟查询耗时 Thread.sleep(2000); // 假设查询结果 String result = "查询结果: 用户数据"; callback.onResult(result); } catch (InterruptedException e) { callback.onError(e); } } } public static void main(String[] args) { // 创建并启动线程 new Thread(new QueryTask(new QueryCallback() { @Override public void onResult(String result) { System.out.println("收到结果: " + result); } @Override public void onError(Exception e) { System.err.println("查询出错: " + e.getMessage()); } })).start(); System.out.println("主线程继续执行..."); } } ``` ### 方式2:使用CallableFuture(通过线程池) 这种方式可以获取线程执行后的返回值,更适用于需要等待结果的场景(引用[3]提到线程池的使用)。 ```java import java.util.concurrent.*; public class QueryWithCallable { // 查询任务实现Callable接口 static class QueryTask implements Callable<String> { @Override public String call() throws Exception { // 模拟查询耗时 Thread.sleep(2000); // 返回查询结果 return "查询结果: 用户数据"; } } public static void main(String[] args) throws Exception { // 创建线程池 ExecutorService executor = Executors.newSingleThreadExecutor(); // 提交任务,返回Future对象 Future<String> future = executor.submit(new QueryTask()); System.out.println("主线程继续执行..."); // 在需要结果时调用get(),会阻塞直到结果返回 String result = future.get(); System.out.println("获取结果: " + result); // 关闭线程池 executor.shutdown(); } } ``` ### 关键点说明 1. **回调机制(方式1)**:适用于异步通知,不阻塞主线程,但需要定义回调接口。 2. **Future机制(方式2)**:通过`future.get()`获取结果时会阻塞,直到任务完成。因此,如果不想阻塞主线程,可以将`future.get()`放在另一个线程中执行,或者使用超时参数(如`future.get(5, TimeUnit.SECONDS)`)。 3. **线程池管理(方式2)**:使用线程池(如`Executors.newSingleThreadExecutor()`)可以避免频繁创建销毁线程的开销,推荐在生产环境中使用[^3]。 4. **异常处理**:在Callable的`call()`方法中抛出异常会被Future.get()重新抛出(封装在ExecutionException中),因此需要适当处理。 ### 总结 - 对于简单的查询任务,可以使用Runnable配合回调。 - 对于需要获取返回值的查询任务,推荐使用Callable线程池(ExecutorService)结合Future。 §§相关问题§§ 1. Java中如何避免Future.get()阻塞主线程? 2. 线程池中submit()execute()方法有什么区别? 3. 如何在多线程查询中处理数据库连接? 4. Java回调机制还有哪些实现方式?</think>### Java线程实现查询功能的代码示例 以下是三种实现方式,均基于标准库实现,包含完整线程状态监控结果处理: #### 方式1:基础Thread实现(带状态监控) ```java public class QueryThread extends Thread { private String result; private final String queryParam; public QueryThread(String param) { this.queryParam = param; } @Override public void run() { try { System.out.println("[" + getName() + "] 状态: " + getState() + " → RUNNABLE"); // 模拟查询耗时 Thread.sleep(1500); // 实际查询逻辑 (示例) result = "查询结果: " + queryParam + " (共" + (new Random().nextInt(100)) + "条)"; } catch (InterruptedException e) { Thread.currentThread().interrupt(); result = "查询中断"; } } public static void main(String[] args) throws InterruptedException { QueryThread thread = new QueryThread("用户数据"); System.out.println("初始状态: " + thread.getState()); // NEW thread.start(); // 启动线程 // 监控线程状态 while(thread.isAlive()) { System.out.println("执行中状态: " + thread.getState()); // TIMED_WAITING/RUNNABLE Thread.sleep(300); } System.out.println("最终状态: " + thread.getState()); // TERMINATED System.out.println("查询结果: " + thread.result); } } ``` #### 方式2:Runnable + Future(推荐) ```java import java.util.concurrent.*; public class QueryExecutor { static class QueryTask implements Callable<String> { private final String param; public QueryTask(String param) { this.param = param; } @Override public String call() { try { // 模拟复杂查询 Thread.sleep(2000); return "成功查询: " + param + " (ID:" + Thread.currentThread().getId() + ")"; } catch (InterruptedException e) { Thread.currentThread().interrupt(); return "查询失败"; } } } public static void main(String[] args) throws Exception { ExecutorService executor = Executors.newFixedThreadPool(3); // 提交多个查询任务 Future<String> future1 = executor.submit(new QueryTask("订单数据")); Future<String> future2 = executor.submit(new QueryTask("商品数据")); System.out.println("主线程继续执行其他任务..."); // 异步获取结果(阻塞直到完成) System.out.println("结果1: " + future1.get()); System.out.println("结果2: " + future2.get()); executor.shutdown(); // 关闭线程池[^3] } } ``` #### 方式3:CompletableFuture(Java 8+ 异步编程) ```java import java.util.concurrent.*; public class AsyncQuery { public static String executeQuery(String param) { try { Thread.sleep(1800); return param + "查询完成!"; } catch (InterruptedException e) { Thread.currentThread().interrupt(); return "查询错误"; } } public static void main(String[] args) { CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> executeQuery("实时数据")); // 非阻塞回调处理 future.thenAccept(result -> System.out.println("回调处理结果: " + result) ); System.out.println("主线程继续执行..."); // 如果需要等待结果 try { System.out.println("直接获取结果: " + future.get(3, TimeUnit.SECONDS)); } catch (Exception e) { e.printStackTrace(); } } } ``` ### 关键特性对比 | 特性 | Thread方式 | Future方式 | CompletableFuture | |--------------------|------------------|---------------------|-----------------------| | **返回值获取** | 需共享变量 | Future.get()阻塞获取 | 回调非阻塞获取 | | **线程管理** | 手动管理 | 线程池自动管理[^3] | 内置ForkJoinPool | | **异常处理** | try-catch内部处理 | 通过ExecutionException | exceptionally()链式处理 | | **状态监控** | 手动实现[^2] | 通过Future.isDone() | 内置状态查询 | | **适用场景** | 简单单次查询 | 批量查询任务 | 复杂异步工作流 | ### 最佳实践建议 1. **线程资源管理**:始终使用`try-with-resources`或显式`shutdown()`关闭线程池[^3] ```java try (ExecutorService executor = Executors.newCachedThreadPool()) { executor.submit(() -> executeQuery("关键数据")); } // 自动关闭 ``` 2. **超时控制**:防止线程阻塞 ```java future.get(5, TimeUnit.SECONDS); // 设置超时时间 ``` 3. **状态监控**:结合引用[^2]实现线程状态跟踪 ```java while (thread.getState() != Thread.State.TERMINATED) { System.out.println("当前状态: " + thread.getState()); Thread.sleep(100); } ``` 4. **异常处理**:通过Future捕获执行异常 ```java try { future.get(); } catch (ExecutionException e) { System.err.println("查询失败: " + e.getCause()); } ``` > **提示**:数据库查询场景需注意: > 1. 每个线程使用独立Connection对象 > 2. 结果集处理需同步(如使用`Collections.synchronizedList()`) > 3. 使用连接池(如HikariCP)避免资源耗尽
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值