java线程实现的三种方式,调用方式,生命周期,sleep和wait区别,ThreadLocal

本文详细讲解了Java中Thread、Runnable和Callable的用法,包括线程生命周期的各个状态,并探讨了主线程与子线程的关系,以及ThreadLocal的内存管理问题。通过实例演示了如何正确使用ThreadLocal以避免内存泄漏。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
代码如下:分别是继承Thread,实现Runable,,事项Callable。
此时运行代码是主线程里分别在跑三个子线程。

package com.cloud.test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Test {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println(Thread.currentThread().getName()+":running.....");
        //调用线程1
        MyThread thread=new MyThread();
        thread.start();
        //调用线程2    (并不能以线程的方式启动,实际上只是创建了一个任务,需要启动一个线程来去执行它)
        Task task=new Task();
        new Thread(task).start();
        //调用线程3
        Task1 task1=new Task1();
        FutureTask<String> futureTask=new FutureTask<>(task1);
        Thread thread1=new Thread(futureTask);
        thread1.start();
        String s = futureTask.get();
        System.out.println(s);


    }


}
//创建线程方式1,继承Thread类,重写run方法
class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+":running.....");
    }
}
//创建线程方式2,实现Run类,重写run方法
class Task implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+":running.....");
    }
}
//创建线程方式3,实现Callable类,重写call方法
class Task1 implements Callable<String> {

    @Override
    public String call() throws Exception {
        System.out.println(Thread.currentThread().getName()+":running.....");
        return "down...............";
    }
}

线程的生命周期:
在这里插入图片描述
从https://www.cnblogs.com/marsitman/p/11228684.html粘了一个图,然后解释一下
说一下这几个状态;
new: 创建线程对象。
runnable: 线程就绪。
blocked: 慢于其它线程获得锁,被其它线程先获得执行权,进入blocked状态,直到锁被释放,该线程从新进入runnable状态,继续抢锁。
waiting: 当线程调用wait或者join时,进入waiting,唤醒后进入runnable状态。
timed waiting: 当线程进入sleep(time),wait(time)时进入timed waiting状态。
running: 获取执行权的正在运行的线程状态。
terminated: 执行结束,进入该状态。

主线程睡眠会影响子线程吗???
不会。
各个线程之间的运行时相互独立的,只按照本身的时间线来走,不受别的线程的影响。主线程休眠与子线程无关。主线程只是人为的称呼,为了方便描述所使用的称呼,各个线程是并行存在的,相互独立运行。

sleep和wait区别
1、所属的类不同:sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。
2、对锁资源的处理方式:sleep不让出系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。
3、一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。
4、sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常。
5、使用范围,sleep可以使用在任何范围,wait只能使用在同步方法和同步代码块。

ThreadLocal
是线程本地存储,在每个线程中都创建了一个 ThreadLocalMap 对象,每个线程可以访问自己内部 ThreadLocalMap 对象内的 value。也就是可以为每个线程创建自己的副本,存储的数据只能供所存储的线程所使用。

如下代码示例为启动两个线程,使用ThreadLocal保存不同数据,证明如此:
保存是将当前执行线程作为KEY,保存的数据作为VALUE,存进ThreadLocalMap里。

static ThreadLocal threadlocal = new ThreadLocal();

    public static void main(String[] args) {
        Task task = new Task();
        new Thread(task).start();
        new Thread(task).start();
    }
    static class Task implements Runnable {
        @Override
        public void run() {
            if (threadlocal.get() == null) {
                threadlocal.set(System.currentTimeMillis());
            }
            System.out.println(Thread.currentThread().getName() + "------>" + threadlocal.get());
        }
    }

在这里插入图片描述
在线程池中使用ThreadLocal为什么会导致内存泄漏???

在线程池中线程的存活时间太长,往往都是和程序同生共死的,这样 Thread 持有的 ThreadLocalMap 一直都不会被回收,再加上 ThreadLocalMap 中的 Entry 对 ThreadLocal 是弱引用(WeakReference),所以只要 ThreadLocal 结束了自己的生命周期是可以被回收掉的。Entry 中的 Value 是被 Entry 强引用的,即便 value 的生命周期结束了,value 也是无法被回收的,导致内存泄露。

线程池中,如何正确使用 ThreadLocal?
在 finally 代码块中手动清理 ThreadLocal 中的 value,调用 ThreadLocal 的 remove()方法。
ThreadLocal使用场景
UserService去调用UserDao和LogDao,那么这通过一个业务里不能开启两个Connection,所以在这个线程里将Connection存储在ThreadLocal里,当调用LogDao的时候也用这个Connection。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值