线程大概内容

本文探讨了多任务和多线程的概念,如何通过Thread、Runnable和Callable创建线程,以及线程池的应用。讲解了线程安全问题及解决方法,包括同步代码块、同步方法和Lock。还涉及线程通信、优先级、生命周期和常见操作。
摘要由CSDN通过智能技术生成

线程、进程、多线程

1、基本概念

  • 多任务
  • 多线程
    • 很多线程是模拟出来的,真正的多线程是指多个cpu,即多核,如服务器。
  • 线程
    • 一个进程可以有多个线程。如视频中可以看视频,听声音,看弹幕
    • main()主线程,入口
    • gc() 垃圾回收线程
  • 程序
  • 进程

2、线程创建(Thread、Runnable、Callable,线程池)

买票时 ,继承Thread要static Runnable不要

  • Thread:

    • 继承thread
    • 重写run()
    • 直接生成对象
    • 对象.start();
      • start()的作用,1.启动当前线程,2.调用当前线程的run()
      • 重复调用start()会报错
      • 对象.run()没有启动线程,只是调用方法而已
  • Runnable :实现接口(优先选择,没有类的单继承缺陷,可以实现多个线程共享数据)

  • 实现Callable接口:

在这里插入图片描述
在这里插入图片描述

  • 线程池
    在这里插入图片描述
    在这里插入图片描述

3、使用线程以及FileUtils下的copyURLToFile(url,name)方法

  • 写一个下载类,下载类中使用了FileUtils.copyURLToFile(new URL(url),new File(name));

    //下载器
    class Downloader{
    //    下载方法
        public void downloader(String url,String name){
    //        FileUtils.copyURLToFile(url,name)
            try {
                FileUtils.copyURLToFile(new URL(url),new File(name));
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("出现异常");
            }
        }
    }
    
  • 写一个线程类,线程类中覆写了run()方法,以及存在url,name 两个成员变量

    public class Thread1 extends Thread {
        private String url;
        private String name;
    
        public Thread1(String url,String name){
            this.url=url;
            this.name=name;
        }
    
        @Override
        public void run() {
            Downloader downloader = new Downloader();
            downloader.downloader(url,name);
            System.out.println("run方法执行,下载了文件+"+name);
        }
    
        public static void main(String[] args) {
            Thread1 thread1 = new Thread1("https://huyaimg.msstatic.com/cdnimage/game/1-MS.png","英雄联盟");
            thread1.start();
        }
    
    }
    

线程的安全问题

  • 问题的提出
    • 多个线程执行的不确定性引起执行结果的不稳定性
    • 多个线程对账本的共享,会造成操作的不完整性,会破坏数据
  • 单例模式(懒汉式)有线程安全问题

1.线程的同步

  • 问题

    • 卖票过程中出现重票或者错票的问题
  • 原因

    • 当线程操作车票的过程中,尚未完成时,其他线程参与进来,也操作车票导致出现线程问题
  • 解决方法

    • 当线程a在操作ticket时,其他线程不能参与进来,知道线程a操作完ticket时,其他线程才可以开始操作ticket。这种情况即使线程a出现了阻塞,也不能改变
  • 在Java中,我们通过同步机制,来解决线程的安全问题

    • 方式一:同步代码块

      synchronize(同步监视器){

      ​ //需要被同步的代码

      }

      //说明:操作共享数据的代码,即为需要被同步的代码

      //共享数据:多个线程共同操作的变量

      //同步监视器,俗称锁。任何一个类的对象,都可以充当锁。

      锁必需是同一个

    • 方式二:同步方法

    • 方式三:同步锁Lock(建议使用)

      • private ReentrantLock lock = new ReentrantLock();
      • lock.lock()
      • lock.unLock()

2.线程的通信

线程通信的例子:先notify() 再 wait()
2个线程交叉打印

  • wait():一旦执行此方法,当前线程就进入阻塞,并释放同步监视器
  • notify():一旦执行此方法,就会唤醒一个被wait()的线程,如果有多个线程被wait,就唤醒优先级搞的那个.
  • notifyAll():一旦执行此方法,就会唤醒所有被wait()的线程

这三个方法必须在同步代码块或者同步方法中使用

调用wait notify notifyAll 方法时都省略了this. or 类.class

wait notify notifyAll 方法的对象必须时同步监视器

wait notify notifyAll 方法时定义在Java.lang.Object下

例题:生产者和消费中的问题

在这里插入图片描述


面试题

1:synchronized 和 Lock的异同

  • 相同:都是解决线程安全问题
  • 不同:
    • synchronized ,在执行完同步代码后,自动释放同步监视器
    • Lock需要手动同步Lock(),手动释放unLock()s

2.sleep() 和wait()的异同

  • 相同:一旦执行方法,都可以让线程进入阻塞状态
  • 不同:
    • 两个方法的声明位置不同:Thread类中声明sleep(),Objcet类汇总声明wait()
    • 调用的要求不同:sleep()可以在任何需要的场景下调用。wait()必须使用在同步代码块中
    • 如果两个方法都存在同步代码块或同步方法中,sleep()不会释放锁,wait()会释放锁

线程中的常用方法

  1. start() 启动线程,并调用run()
  2. run():线程要执行的代码写在方法里
  3. currentThread()静态代码,返回执行当前代码的线程
  4. getName() 获得线程的名字
  5. setName() 设置线程的名字
  6. yield() 释放当前cpu的执行权
  7. join() 在线程a中调用线程b的join(),此时线程a进入阻塞状态,直到线程b执行完,线程a才继续执行
  8. stop() 强制结束线程(不推荐使用)
  9. sleep(1000) 线程阻塞1s
  10. isAlive() 判断当前线程是否存活

线程的优先级

优先级只是概率,不代表一定优先级高的就先执行

  1. getPriority()获取优先级
  2. setPriority()设置优先级
    1. Thread.MIN_PRIORITY 10
    2. Thread.MAX_PRIORITY 1
    3. Thread.NORM_PRIORITY 5

线程的生命周期在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用多线程处理List内容的步骤如下: 1. 导入`threading`模块,它提供了多线程支持。 2. 定义一个`process_item()`函数来处理列表中的每个元素。这个函数将被每个线程调用。 3. 创建一个线程池,可以使用`ThreadPoolExecutor`类。通过指定最大线程数来控制并发执行的线程数量。 4. 将要处理的列表分成若干个块,每个块的大小由可以处理的线程数决定。 5. 遍历列表块,为每个块创建一个新的线程并启动。 6. 等待所有线程执行完毕,使用`.join()`方法等待每个线程完成。 7. 最后,合并或处理线程处理后的结果。 下面是一个示例代码,该代码演示了如何使用多线程处理列表: ```python import threading from concurrent.futures import ThreadPoolExecutor def process_item(item): # 这里可以对列表中的每个元素进行处理 print(item) def main(): # 处理的列表 my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 创建线程池 executor = ThreadPoolExecutor(max_workers=4) # 分割列表 chunk_size = len(my_list) // executor._max_workers chunks = [my_list[i:i+chunk_size] for i in range(0, len(my_list), chunk_size)] # 启动线程 for chunk in chunks: executor.submit(process_item, chunk) # 等待所有线程完成 executor.shutdown() if __name__ == "__main__": main() ``` 在上面的示例中,我们将列表块分为四个,最大线程数为4。在`process_item()`函数中,我们只是简单地打印出每个列表块。你可以根据需要修改`process_item()`函数来适应你的具体需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值