Java--多线程知识点

这篇博客详细介绍了Java中的多线程概念,包括进程和线程的区别、线程的状态、如何创建和启动线程(通过继承Thread类和实现Runnable接口)、线程调度的方法,如sleep()、join()、yield()等,并探讨了线程同步的重要性,以同步方法和同步代码块为例进行了说明。此外,还对比了线程安全和非线程安全类型的优缺点以及在不同场景下的选择。

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

*     进程和线程
     *     (应用程序的执行实例)--》    进程        《--(有独立的内存空间和系统资源)
     *     (CPU调度和分派的基本单位)    线程        《--(进程中执行运算的最小单位,可完成一个独立的顺序控制流程)
 * 
 *     多线程
     *     什么是多线程
         *    如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为“多线程”
             *    多个线程交替占用CPU资源,而非真正的并行执行
             *    多线程好处
         *    充分利用CPU的资源
             *    简化编程模型
             *    带来良好的用户体验
 *    线程的状态:
     *(1)、创建状态
     *(2)、就绪状态
     *(3)、阻塞状态
     *(4)、运行状态    
     *(5)、死亡状态
 * 
 *     主线程
     * Thread类
         * Java提供了java.lang.Thread类支持多线程编程
     *     主线程
         * main()方法即为主线程入口
         *     产生其他子线程的线程
         *     必须最后完成执行,因为它执行各种关闭动作
 *     示例:
 * public static void main(String args[]) {
        Thread t= Thread.currentThread(); 
        System.out.println("当前线程是: "+t.getName()); 
        t.setName("MyJavaThread"); 
        System.out.println("当前线程名是: "+t.getName()); }
 * 
 *     线程的创建和启动
     *     在Java中创建线程的两种方式
         *     继承java.lang.Thread类
         *     实现java.lang.Runnable接口
 *     使用线程的步骤
     *     1、定义线程-->2、创建线程对象-->3、启动线程-->4、终止线程
 * 
 *     继承Thread类创建线程2-1
     *     定义MyThread类继承Thread类
     *     重写run()方法,编写线程执行体
     *     创建线程对象,调用start()方法启动线程
 * 
 * run()方法和start()方法的区别
     * 1)run()线程体:每个线程对象都要执行的
     * 2)start()线程的启动方法,启动之后线程进入就绪状态,通过
     抢占CPU资源来执行线程任务 
 * 
public class MyThread extends Thread{
    //重写run()方法
    public void run(){
        for(int i=1;i<100;i++){            
        System.out.println(
        Thread.currentThread().getName()+":"+i);
}}}

public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start(); //启动线程
}

 *     继承Thread类创建线程2-2
     *     多个线程交替执行,不是真正的“并行”
     *     线程每次执行时长由分配的CPU时间片长度决定
 * 
 *     常见问题
     *     启动线程是否可以直接调用run()方法?
     *     调用run():
         *     只有主线程一条执行路径
     *     调用start()
         *     多条执行路径,主线程和子线程并行交替执行
 * 
 *     实现Runnable接口创建线程
     *     定义MyRunnable类实现Runnable接口
     *     实现run()方法,编写线程执行体
     *     创建线程对象,调用start()方法启动线程
     * 
public class MyRunnable implements Runnable{(这里实现Runnable接口)
    public void run(){(run()方法中编写线程执行的代码)
        for(int i=1;i<100;i++){            
        System.out.println(
        Thread.currentThread().getName()+":"+i);
}}}

public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();(创建线程对象)
        Thread myThread = new Thread(myRunnable);    
        thread.start(); //启动线程}

 *     比较两种创建线程的方式
 * 
     *     继承Thread类
         *     编写简单,可直接操作线程
         *     适用于单继承
     *     实现Runnable接口
         *    避免单继承局限性
         *    便于共享资源
 * 
 *     线程调度
     *     线程调度指按照特定机制为多个线程分配CPU的使用权
     *    一些常用方法
     *4.1 currentThread():返回对当前正在执行的线程对象的引用。
     *4.2 getId():返回此线程的标识符
     *4.3 getName():返回此线程的名称
     *4.4 getPriority():返回此线程的优先级
     *4.5 isAlive():测试这个线程是否还处于活动状态。
         *    什么是活动状态呢?
             *    活动状态就是线程已经启动且尚未终止。线程处于正在运行或准备运行的状态。
     *4.6 sleep(long millis):使当前正在执行的线程以指定的毫秒数“休眠”(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。
     *4.7 interrupt():中断这个线程。
     *4.8 interrupted() 和isInterrupted():
         *    interrupted():测试当前线程是否已经是中断状态,执行后具有将状态标志清除为false的功能
         *    isInterrupted(): 测试线程Thread对相关是否已经是中断状态,但部清楚状态标志
     *4.9 setName(String name):将此线程的名称更改为等于参数 name 。
     *4.10 isDaemon():测试这个线程是否是守护线程。
     *4.11 setDaemon(boolean on):将此线程标记为 daemon线程或用户线程。
     *4.12 join():
         *    在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,
         主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,
         也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。
         *    join()的作用是:“等待该线程终止”,这里需要理解的就是该线程是指的主线程等待子线程的终止。
         也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行
         *4.13 yield():
         *yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU时间。
         *注意:放弃的时间不确定,可能一会就会重新获得CPU时间片。
     *4.14 setPriority(int newPriority)
 * 
 *     线程休眠
     *     让线程暂时睡眠指定时长,线程进入阻塞状态
     *     睡眠时间过后线程会再进入可运行状态
 * public static void sleep(long millis)
 * 示例:
 public class Wait {
    public static void bySec(long s) {
         for (int i = 0; i < s; i++) {
             System.out.println(i + 1 + "秒");
             try {
    Thread.sleep(1000); 
             } catch (InterruptedException e) {
    e.printStackTrace();
             }}}}
 
 *     线程的强制运行2-1
     *     使当前线程暂停执行,等待其他线程结束后再继续执行本线程
        public final void join()
        public final void join(long mills)
        public final void join(long mills,int nanos)
 * 
 * millis:以毫秒为单位的等待时长
 * nanos:要等待的附加纳秒时长
 *     需处理InterruptedException异常
 * 
 *     线程的强制运行2-2
 * 
  public static void main(String[] args) {
      Thread temp = new Thread(new MyThread());
      temp.start();
      for(int i=0;i<20;i++){
           if(i==5){                
           try {
    temp.join();---》(阻塞主线程,子线程强制执行)
           } catch (InterruptedException e) {
    e.printStackTrace(); }}            
     System.out.println(Thread.currentThread().getName()+"运行:"+i);
      } 
      //省略代码…
}
    
 *     线程的礼让2-1
     *     暂停当前线程,允许其他具有相同优先级的线程获得运行机会
     *     该线程处于就绪状态,不转为阻塞状态
 * public static void yield()
 *     只是提供一种可能,但是不能保证一定会实现礼让
 * 示例:
 public class MyThread implements Runnable{
     public void run(){
          for(int i=0;i<5;i++){
        System.out.println(Thread.currentThread().
              getName()+"正在运行:"+i);
         if(i==3){
            System.out.print("线程礼让:");
        Thread.yield();    
                    } } }}
 * 
 * 
 *     同步方法2-1
     *     使用synchronized修饰的方法控制对类成员变量的访问
         *     访问修饰符 synchronized 返回类型 方法名(参数列表){……}
     *     或者
         *    synchronized 访问修饰符 返回类型 方法名(参数列表){……}
 *     注意:synchronized就是为当前的线程声明一把锁
 * 示例:
// 同步方法:售票
public synchronized void sale() {    
    if (count <= 0) {
        flag = true;
        return;
     }
       // 省略代码:修改数据
       // 省略代码:显示信息
 }
 *     同步代码块2-1
     synchronized(syncObject){
    //需要同步的代码
    }
     *     syncObject为需同步的对象,通常为this
     *     效果与同步方法相同
    public void run() {
    while (true) {
        synchronized (this) {   //同步代码块
        // 省略修改数据的代码......
       // 省略显示信息的代码......
    }}}
 * 
 *     多个并发线程访问同一资源的同步代码块时
     *    同一时刻只能有一个线程进入synchronized(this)同步代码块
     *    当一个线程访问一个synchronized(this)同步代码块时,其他synchronized(this)同步代码块同样被锁定
     *    当一个线程访问一个synchronized(this)同步代码块时,其他线程可以访问该资源的非synchronized(this)同步代码
 * 
 *     线程安全的类型
     *     查看ArrayList类的add()方法定义     
public boolean add(E e) {
       ensureCapacityInternal(size + 1);     (集合扩容,确保能新增数据)
      elementData[size++] = e;                (在新增位置存放数据)
        return true;
}
     *     ArrayList类的add()方法为非同步方法
     *     当多个线程向同一个ArrayList对象添加数据时,可能出现数据不一致问题
 *    提示: ArrayList为非线程安全的类型
 *     
 *     线程安全的类型
 * 
 *-------------------------------------------------------------------------------------|
 *                 |    方法是否同步    |    效率比较    |        适合场景        |
 *-------------------------------------------------------------------------------------|
 *     线程安全        |    是            |    低        |    多线程并发共享资源|
 *-------------------------------------------------------------------------------------|
 *     非线程安全        |    否            |    高        |    当线程                  |
 *-------------------------------------------------------------------------------------|
 *     为达到安全性和效率的平衡,可以根据实际场景来选择合适的类型
 * 
 * 
 *     常见类型对比2-1
     * Hashtable  &&  HashMap
         *     Hashtable
             *     继承关系
                 *     实现了Map接口,Hashtable继承Dictionary类
             *    线程安全,效率较低
             *    键和值都不允许为null
         *    HashMap
             *    继承关系
                 *    实现了Map接口,继承AbstractMap类
             *    非线程安全,效率较高
             *    键和值都允许为null
         *     StringBuffer  &&  StringBuilder
             *     前者线程安全,后者非线程安全
    
 * 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值