当前位置: 首页 > news >正文

Java 第十章线程(2)

目录

多线程

​编辑

概念

多线程优点:

多线程的缺点:

线程同步

实例

同步锁

特点:

实例:

线程通信

实例1

 实例2

新增创建线程方式


多线程


概念

多线程:
指的是在程序中可以创建多个线程来执行不同的任务,Java语言是支持创建多线程
何时需要用多线程:
当需要同时执行多个任务时


多线程优点:

  • 提升程序响应的速度
  • 提升cpu利用率
  • 改善代码结构(例如可以将大任务拆分称多个小任务

多线程的缺点:

  • 线程越多,占用的内存越大(线程也是程序,程序需要占用内存)
  • 多线程需要协调和管理,所以需要跟踪管理线程,使得cpu开销变大;
  • 线程之间同时对共享资源的访问会相互影响,如果不加以控制会导致数据出错

线程同步

多线程同步:多个线程同时读到同一份共享资源时,可能会引发冲突。所以引入线程同步机制。

同步:排队+锁

  • 几个线程之间要排队,一个个对共享资源进行操作,而不是同时进行操作;
  • 为了保证数据在方法中被访问时的正确性,在访问时加入锁机制

实例

/* 解决方法:
    为核心的代码(出票,抢购,秒杀)进行加锁,只能一次一个线程对同步代码块(方法)进行访问
*/
public class TicktThread extends Thread{
    static int n= 10;//票数
    static  Object object = new Object();
    /*
    synchronized修饰代码块
    synchronized(同步锁){

          }
    同步锁:同步锁可以是Java中任意的类的对象,对象是唯一的;
    此对象是记录有没有线程进入到同步代码块。
     */
//    @Override
//    public void run() {
//        while (true){
//            synchronized (object){
//            if (n >0) {
//                System.out.println(Thread.currentThread().getName()+"买到了"+n);
//                n--;
//            }else {
//                break;
//            }
//        }
//        }
//    }

    @Override
    public void run() {
        while (true){
            print();
            if (n <= 0) {
                break;
            }
        }
    }
    /*
    synchronized修饰的方法,方法位同步方法
    这时同步锁对象就不需要我们自己提供了,会自己提供
    当方法如果时非静态方法时锁对象是this
    当方法如果是静态方法时,锁对象是类对象(类对象一个类只有一个)
     */
    public static synchronized void print() {
        if (n > 0) {
            System.out.println(Thread.currentThread().getName() + "买到了" + n);
            n--;
        }
    }

}
public class Test {
    public static void main(String[] args) {
        TicktThread thread = new TicktThread();
        thread.setName("窗口1:");
        TicktThread thread1 = new TicktThread();
        thread1.setName("窗口2:");
        thread1.start();
        thread.start();
    }
}

同步锁

  • 确保一个时间点只有一个线程访问共享资源。
  • 可以给共享资源加一把锁,哪个 线程获取了这把锁,才有权利访问该共享资源

特点:

同步锁可以是任何对象,必须唯一,保证多个线程获得是同一个对象(用来充当锁标记).

同步执行过程

  1. 第一个线程访问,锁定同步对象,执行其中代码.
  2. 第二个线程访问,发现同步对象被锁定,无法访问.
  3. 第一个线程访问完毕,解锁同步对象.
  4. 第二个线程访问,发现同步对象没有锁,然后锁定并访问

在Java代码中实现同步

使用synchronized(同步锁)关键字同步方法或代码块。

synchronized (同步锁){ // 需要被同步的代码; }

synchronized还可以放在方法声明中,表示整个方法,为同步方法。

例如: public synchronized void show (String name){

/ 需要被同步的代码;

}


实例:

模拟卖票

两个窗口分别售票,票数为10张



public class Test {
    public static void main(String[] args) {
        TicktThread thread = new TicktThread();
        thread.setName("窗口1:");
        TicktThread thread1 = new TicktThread();
        thread1.setName("窗口2:");
        thread1.start();
        thread.start();
    }
}
public class TicktThread extends Thread{
    static int n= 10;//票数
    static  Object object = new Object();
    public void run() {
        while (true){
            synchronized (object){
            if (n >0) {
                System.out.println(Thread.currentThread().getName()+"买到了"+n);
                n--;
            }else {
                break;
            }
        }
     }
 }

线程通信

线程通讯指的是多个线程通过相互牵制,相互调度,即线程间的相互作用。

实例1

package com.wyk.javathread.demo5;

import com.wyk.javathread.demo4.TicktThread;

public class Test {
    public static void main(String[] args) {
        TiicketTask task = new TiicketTask();
        Thread thread = new Thread("窗口1");
        Thread thread1 = new Thread("窗口2");
        thread.start();
        thread1.start();
    }
}
package com.wyk.javathread.demo5;

public class TiicketTask implements Runnable{
    Object object = new Object();
    int n = 10;
//    @Override
//    public void run() {
//        while (true){
//            synchronized (object){//object,this
//            if (n>0) {
//                System.out.println(Thread.currentThread().getName()+"买到了"+n);
//                n--;
//            }else {
//                break;
//            }
//          }
//
//        }
//
 //   }

    public synchronized void print(){
        if (n>0) {
            System.out.println(Thread.currentThread().getName()+"买到了"+n);
            n--;
        }

    }


    @Override
    public  void run() {
        while (true){
            this.print();
            if (n<=0){
                break;
            }
        }

    }
}

  • wait一旦执行此方法,当前线程就进入阻塞状态,并释放同步锁对象。
  • notify一旦执行此方法,就会唤醒被wait的一个线程。如果有多个线程被wait, 就唤醒优先级高的那个。
  • notifyAll一旦执行此方法,就会唤醒所有被wait的线程。
  • 注意: .wait(),notify(),notifyAll()三个方法必须使用在同步代码块或同步方法中

 实例2

package com.wyk.javathread.demo6;

public class Test {
    public static void main(String[] args) {
        PrintNumTask task = new PrintNumTask();
        Thread thread = new Thread(task, "线程1");
        Thread thread1 = new Thread(task,"线程2");
        thread.start();
        thread1.start();
    }
}
package com.wyk.javathread.demo6;

public class PrintNumTask implements Runnable{
    int num = 0;
    Object object= new Object() ;
    /*
    notify();wait();必须在同步代码块中进行
    必须使用同步对象进行调用
     */
    @Override
    public void run() {
      while (true){
          synchronized (object){
          object.notify();//唤醒外面等待的线程
              try {
                  Thread.sleep(1000);
              } catch (InterruptedException e) {
                  throw new RuntimeException(e);
              }
              if (num <=100) {
              System.out.println(Thread.currentThread().getName()+":"+(++num));
          }else {
              break;
          }
          try {
              object.wait();//让线程等待
          } catch (InterruptedException e) {
              throw new RuntimeException(e);
          }
      }
      }
    }
}

新增创建线程方式


实现Callable接口与使用Runnable相比,Callable功能更强大些.

  •  相比run()方法,可以有返回值
  • 方法可以抛出异常 • 支持泛型的返回值
  • 需要借助FutureTask类,获取返回结果

接收任务

FutureTask futureTask = new FutureTask(任务);

创建线程

Thread t = new Thread(futureTask);

t.start();

Integer val = futureTask.get();获得线程call方法的返回

相关文章:

  • MarsCode 49
  • 细说STM32F407单片机1个ADC使用DMA同时采集3个输入通道的方法
  • ProfiNet转EtherNet/IP攻克罗克韦尔PLC与光伏电站监控系统连接难题的通讯配置技术
  • Pytorch实现之结合SE注意力和多种损失的特征金字塔架构GAN的图像去模糊方法
  • CLIP学习笔记
  • 安全运维,等保测试常见解决问题。
  • 智慧校园系统在学生学习与生活中的应用
  • RK Android11 WiFi模组 AIC8800 驱动移植调试记录
  • 力扣-回溯-37 解数独
  • JavaScript异步编程方式多,区别是什么?
  • 有时候通过无线上网,有线共享局域网通过该有线为网关进行上网,设置指定的网关IP信息
  • UE5 编辑器辅助/加强 插件搜集
  • C#使用Semantic Kernel:接入本地deepseek-r1
  • 【多模态处理篇五】【DeepSeek文档解析:PDF/Word智能处理引擎】
  • C#初级教程(6)——函数:从基础到实践
  • 后端之路——阿里云OSS云存储
  • 【JavaScript进阶】构造函数数据常用函数
  • 【AI】openEuler 22.03 LTS SP4安装 docker NVIDIA Container Toolkit
  • Java集合框架全解析:从LinkedHashMap到TreeMap与HashSet面试题实战
  • 微信小程序修改个人信息头像(uniapp开发)
  • 中国经济新动能|警惕数字时代下经济的“四大极化”效应
  • 8大类1000多支,中国红十字会已建成10万人规模救援队伍
  • 中国难以承受高关税压力?外交部:任何外部冲击都改变不了中国经济基本面
  • 欧盟官员:欧盟酝酿对美关税政策反制措施,包含所有选项
  • 一周观展|上海浦东美术馆透纳展还剩最后5天
  • “彩虹滑道”项目两男童相撞飞跌出去,景区:工作人员误判导致