多线程,Lock,ThreadPool,voliate

本文详细解析了程序、进程和线程的概念及其区别,探讨了线程的生命周期、线程安全、锁机制以及线程同步的方法。同时,介绍了线程创建的不同方式,并对比了各种方法的特点。

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

程序(program) 为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。
进程(process) 程序的一次执行过程,或是正在运行的一个程序。是一个动态的过程:有它自身的产生、存在和消亡的过程。生命周期 ,进程作为资源分配的单位,系统在运行时会为每个进程分配不同的内存区域。
线程(thread) 进程可进一步细化为线程,是一个程序内部的一条执行路径。
若一个进程同一时间并行执行多个线程,就是支持多线程的
线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器(pc),线程切换的开销小
一个进程中的多个线程共享相同的内存单元/内存地址空间它们从同一堆中分配对象,可以访问相同的变量和对象。这就使得线程间通信更简便、高效。但多个线程操作共享的系统资源可能就会带来安全的隐患。

并行:多个CPU同时执行多个任务。
并发:一个CPU(采用时间片)同时执行多个任务。

常用方法:
static void yield():线程让步
暂停当前正在执行的线程,把执行机会让给优先级相同或更高的线程
若队列中没有同优先级的线程,忽略此方法
join() :当某个程序执行流中调用其他线程的 join() 方法时,调用线程将被阻塞,直到 join() 方法加入的 join 线程执行完为止
线程类型:
守护线程和用户线程,用户线程就是我们自己调用的线程,比如main方法,守护线程比如gc线程,特点,守护线程会在用户线程调用结束的时候停止。

生命周期:
在这里插入图片描述

线程安全(锁):
AQS:AbstractQueuedSynchronizer,即队列同步器。它是构建锁或者其他同步组件的基础框架

单例懒汉线程安全模式:

public class ThreadTest {
  private static ThreadTest single=null;
    public ThreadTest() {
    }
    public static ThreadTest getThreadTest() {
       if (single==null){
           synchronized (ThreadTest.class){
               if (single==null){
               single=new ThreadTest();
               }
           }
       }
       return single;
  }

死锁示例:

public class ThreadTest {
    public static void main(String[] args) {
        Object a1 = new Object();
        Object a2 = new Object();
        new Thread(()->{
            synchronized (a1){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(a1+"线程1");
                synchronized (a2){
                    System.out.println(a2+"线程1");
                }
            }
        }      ).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (a2){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }
                    System.out.println(a2+"线程2");
                    synchronized (a1){
                        System.out.println(a1+"线程2");
                    }
                }
            }
        }).start();
    }
}

Lock(锁)
Lock是显式锁(手动开启和关闭锁,别忘记关闭锁),synchronized是隐式锁,出了作用域自动释放
Lock只有代码块锁,synchronized有代码块锁和方法锁
使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且具有更好的扩展性(提供更多的子类)

class A {
    private final  ReentrantLock lock= new ReentrantLock();
    public void m() {
        lock.lock();
        try {
//保证线程安全的代码;
        } finally {
            lock.unlock();
        }
    }
}

线程同步常用方法:
wait():令当前线程挂起并放弃CPU、同步资源并等待,使别的线程可访问并修改共享资源,而当前线程排队等候其他线程调用notify()或notifyAll()方法唤醒,唤醒后等待重新获得对监视器的所有权后才能继续执行。
notify():唤醒正在排队等待同步资源的线程中优先级最高者结束等待
notifyAll ():唤醒正在排队等待资源的所有线程结束等待
这三个方法只有在synchronized方法或synchronized代码块中才能使用

voliate
voliate对变量的读写是线程安全的,但是变量的操作却不是线程安全的。例如多线程对某个变量做++
i++

线程创建
1;继承Thread
2,implements Runnable
1和2的区别:
避免了单继承的局限性
多个线程可以共享同一个接口实现类的对象,非常适合多个相同线程来处理同一份资源。

3,implements Callable
4,ThreadPool

public class ThreadTest {
    public static void main( String[] args){
        //Thread方式
        Thread1 test = new Thread1();
        test.start();
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName()+i);

        }
        //Runable方式
        Runable2 test2 = new Runable2();
        final Thread thread = new Thread(test2);
        Thread thread2 = new Thread(test2);
        thread.start();
        thread2.start();
        
         //Callable方式
        ThreadTest test3= new ThreadTest();
        FutureTask<String> futureTask = new FutureTask<>(test3);
        new Thread(futureTask).start();
        String s = futureTask.get();
        System.out.println(s);
        
        //线程池创建线程
        ExecutorService executorService = ThreadPoolExecutor.getExecutorService();
        for (int i = 0; i < 5; i++) {
            Future<String> submit = executorService.submit(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return Thread.currentThread().getName()+"hello";
                }
            });
            System.out.println(submit.get());
        }


    }
}
//1;继承Thread
class Thread1 extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100;
        i++){
            System.out.println(Thread.currentThread().getName()+i);

        }

    }
}
//2,implements Runnable
class Runable2 implements Runnable{

    public void run() {
        for (int i = 0; i < 100;
             i++){
            System.out.println(Thread.currentThread().getName()+i);

        }
    }
}
//implements Callable
class ThreadTest implements Callable<String> {
    @Override
    public String call() throws Exception {
        System.out.println(Thread.currentThread().getName() + "hello");
        return "hello";
    }
}
//线程池
class ThreadPoolExecutor {
    private static ExecutorService executorService = Executors.newFixedThreadPool(2);
    private ThreadPoolExecutor() {
    }
    public static ExecutorService getExecutorService() {
        return executorService;
    }
}

ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor void execute(Runnable command) :执行任务/命令,没有返回值,一般用来执行 Runnable
Future submit(Callable task):执行任务,有返回值,一般又来执行
Callable void shutdown() :关闭连接池
Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池
Executors.newCachedThreadPool():创建一个可根据需要创建新线程的线程池
Executors.newFixedThreadPool(n); 创建一个可重用固定线程数的线程池
Executors.newSingleThreadExecutor() :创建一个只有一个线程的线程池
Executors.newScheduledThreadPool(n):创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值