首页 > 其他分享 >多线程

多线程

时间:2023-08-21 13:23:46浏览次数:25  
标签:run Thread void 线程 new 多线程 public

1.线程

1.1 创建

  • 继承 Thread类
public class MyThread extends Thread{
    /**
     * Thread 类本质上是实现了Runnable 接口的一个实例,代表一个线程的实例。启动线程的唯一方
     * 法就是通过Thread 类的start()实例方法。start()方法是一个native 方法,它将启动一个新线
     * 程,并执行run()方法。
     */
    public void run(){
        System.out.println("My Thread");
    }

    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();
    }
}
  • 实现Runnable接口
public class MyThread1 implements Runnable{

    @Override
    public void run() {
        System.out.println("My Thread 1");
    }

    public static void main(String[] args) {
        MyThread1 thread1 = new MyThread1();
        Thread thread = new Thread(thread1);
        thread.start();
    }
  • 有返回值线程
public class MyThread2 implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        return 1;
    }

    /**
     * 有返回值的任务必须实现Callable 接口,类似的,无返回值的任务必须Runnable 接口。执行
     * Callable 任务后,可以获取一个Future 的对象,在该对象上调用get 就可以获取到Callable 任务
     * 返回的Object 了,再结合线程池接口ExecutorService 就可以实现传说中有返回结果的多线程了。
     * @param args
     */
    public static void main(String[] args) {
        //创建一个线程池
        ExecutorService pool = Executors.newFixedThreadPool(5);
        // 创建多个有返回值的任务
        List<Future> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            Callable c = new MyThread2();
            // 执行任务并获取Future 对象
            Future f = pool.submit(c);
            list.add(f);
        }
        // 关闭线程池
        pool.shutdown();
        // 获取所有并发任务的运行结果
        for (Future f : list) {
        // 从Future 对象上获取任务的返回值,并输出到控制台
            try {
                System.out.println("res:" + f.get().toString());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
}
  • 基于线程池
/**
* 线程和数据库连接这些资源都是非常宝贵的资源。那么每次需要的时候创建,不需要的时候销
* 毁,是非常浪费资源的。那么我们就可以使用缓存的策略,也就是使用线程池。
*/
// 创建线程池
ExecutorService threadPool = Executors.newFixedThreadPool(10);
while(true) {
  threadPool.execute(new Runnable() { // 提交多个线程任务,并执行
      @Override
      public void run() {
          System.out.println(Thread.currentThread().getName() + " is running ..");
          try {
              Thread.sleep(3000);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
      }
  });
}

1.2 线程池

顶级接口Executor 执行线程的工具 线程池接口ExectorService

  • newCachedThreadPool

1.3 生命周期

  • 新建状态:new线程后
  • 就绪:调用start
  • 运行:获得cpu,执行run
  • 阻塞:1.等待阻塞:wait方法,进入等待队列。 2.同步阻塞:获取对象同步锁时,其被占用,则放入锁池。 3.其他阻塞:现场sleep或join或发出IO请求,设置为阻塞,请求完转入可运行状态
  • 死亡:1.正常死亡:run/call完成 2.异常结束:线程抛出未捕获的异常。 3.调用stop:容易死锁。

1.3.1 终止线程方式

  • 正常结束
  • 使用退出标志
public class ThreadSafe extends Thread{
    // volatile使exit同步
    private volatile boolean exit = false;

    public void run(){
        while (!exit){
            
        }
    }
}
  • Interrupt方法
    1.线程阻塞状态:调用interrupt,抛出InterruptException 异常,break跳出循环,结束线程
    2.未阻塞状态:isInterrupted()判断线程的中断标志来退出
//2.isInterrupted()方法
while (!isInterrupted()) { //非阻塞过程中通过判断中断标志来退出
    try {
        Thread.sleep(5 * 1000);//阻塞过程捕获中断异常来退出
    } catch (InterruptedException e) {
        e.printStackTrace();
        break;//捕获到异常之后,执行break 跳出循环
    }
}
  • stop方法:会释放子线程所持有的所有锁,线程不安全

1.3.2 sleep和wait

  • sleep:属于Thread

1.3.3 start和run

1.4 Java后台线程

1.5 锁

1.5.1 乐观锁

拿数据不上锁,更新时比较版本号,加锁操作
CAS操作实现,比价当前值和传入值是否一样,一样更新

1.5.2 悲观锁

拿数据上锁,别的线程会block直达拿到锁
AQS框架下,先尝试CAS乐观锁获取锁,拿不到转化为悲观锁

1.5.2.1 synchronized 同步锁

可以把任意一个非NULL 的对象当作锁。他属于独占式的悲观锁,同时属于可重入锁。

  • 作用范围

1.5.2.2 ReentrantLock

1.5.3 自旋锁

如果持有锁的线程能在很短时间内释放锁资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态,它们只需要等一等(自旋),等持有锁的线程释放锁后即可立即获取锁,这样就避免用户线程和内核的切换的消耗。

1.5.4 信号量

标签:run,Thread,void,线程,new,多线程,public
From: https://www.cnblogs.com/lwx11111/p/17645754.html

相关文章

  • 4.7 C++ Boost 多线程并发库
    Boost库是一个由C/C++语言的开发者创建并更新维护的开源类库,其提供了许多功能强大的程序库和工具,用于开发高质量、可移植、高效的C应用程序。Boost库可以作为标准C库的后备,通常被称为准标准库,是C标准化进程的重要开发引擎之一。使用Boost库可以加速C应用程序的开发过程,提高代码质......
  • 探索Java中的并发编程:多线程同步与性能优化
    在后端开发领域,Java作为一门强大的编程语言,广泛应用于构建高性能和并发性能强大的应用程序。本文将深入探讨Java中的并发编程,重点关注多线程同步机制与性能优化策略。通过结合实际代码示例,为读者提供关于并发编程的深奥知识和实用方法。1.并发编程概述与原理并发编程是指多个线程......
  • 多线程爬虫
    pythonGIL锁同步线程的一种机制,即使在多处理器也是仅有一个线程在执行避免GIL用multiprocessing替代Thread用多进程代替多线程,每个进程有自己的独立的GIL,不会出现进程之间的GIL争抢。多进程的创建和销毁开销也会更大,成本高LOCK锁原子操作 一步是计算,一步的赋值,所以不是......
  • 为什么 Java 坚持多线程不选择协程?
    1.引言在编程的世界里,多线程和协程是两种主要的并发处理方法。Java,作为一种广泛使用的编程语言,从其早期版本开始就深入支持多线程。那么,为什么Java坚持使用多线程而不是协程?要理解这个问题,我们需要深入探讨两者之间的差异以及Java的设计哲学。2.多线程和协程的基本差异多线程:线程......
  • 多线程 问答
    1、线程的状态或什么周期新建,就绪,运行,阻塞,销毁new,runnable,running,blocked,terminated java角度  2、java里面,wait和sleep的区别wait是object的方法,等待时会释放锁sleep是线程Thread的方法,睡眠时不会释放持有的对象锁,需要捕获异常。结束睡眠后,进入runnable状态。......
  • c++ 多线程
    #include<iostream>#include<functional>#include<thread>#include<future>//std::promise,std::future#include<chrono>voidprint_int(std::future<int>&fut){intx=fut.get();......
  • C++ 多线程详解之异步编程 std::packaged_task
    std::packaged_task将任何可调用对象(比如函数、lambda表达式等等)封装成一个task,可以异步执行。执行结果可以使用std::future获取。比如下面的例子,构造一个std::packaged_task后,get_future()函数返回一个std::future对象,可以获取task异步或者同步执行的结果。#includ......
  • 在C++中实现多线程异步TCP消息发送
    本文主要解释了在C++中如何实现一个多线程,异步发送TCP消息的系统。我们将会用到C++的标准库和Boost.Asio库。基础知识TCP(TransmissionControlProtocol):是一种面向连接的、可靠的、基于字节流的通信协议。它在两个网络节点之间创建一个稳定的连接,以便可以交换字节流。多线程编程:......
  • 爬虫速度翻倍!多线程技术助你提升批量爬虫采集效率
       今天要和大家分享一些关于如何利用多线程技术提升批量爬虫采集效率的实用技巧。如果你也在面对大量数据采集任务的时候疲于奔命,那么这些经验对你来说将非常有帮助。废话不多说,让我们开始吧!1.多线程是什么?——理解多线程的概念多线程是指在一个程序中同时运行多个......
  • 多线程的“锁”
    其实,很多初学者(包括我自己)初期学习多线程时都被视频带偏了...虽然我始终认为培训班的视频是最适合非科班零基础入门的,但是在多线程方面,无一例外都讲得比较糟糕。感触很深的一点是:很多新手觉得多线程难,并不是因为volatile、ReentrantLock或者Executor线程池,而是从一开始就没弄明白......