IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java高级(一)多线程、同步、无限等待示例 -> 正文阅读

[Java知识库]Java高级(一)多线程、同步、无限等待示例

目录

多线程

基本概念

创建线程(两种方法)

方法一:创建线程类

方法二:实现Runnable接口

多线程原理:

线程安全问题(同步)

同步代码块

同步方法

Lock锁

线程状态

TIMED_WAITING:计时等待

Waiting(无限等待)


多线程

基本概念

并行与并发

  • 并发:指两个或多个事件在同一个时间段内发生。
  • 并行:指两个或多个事件在同一时刻发生(同时发生)???

线程与进程的关系

进程是程序的一次执行过程,也是系统运行程序的基本单位

线程是进程中的一个执行单元,负责当前进程中程序的执行,1个进程中至少有1个线程

一个程序运行后至少有一个进程,一个进程中可以包含多个线程

线程的调度

  • 分时调度
    所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。
  • 抢占式调度
    优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。

JVM执行main方法,main会进入栈内存;JVM会找操作系统开辟一条main方法通向cpu的执行路径,cpu就可以通过这个路径来执行main方法 ;这个路径就是主线程

创建线程(两种方法)

方法一:创建线程类

自定义类继承Thread类,重写run方法

public class Mythread  extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            System.out.println("线程"+i);
        }
    }
}

创建线程对象并且启动线程

new Mythread().start();

start()方法会自动调用run方法

方法二:实现Runnable接口

public class test1 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("线程");
        }
    }
}

创建线程对象并且启动线程

new Thread(new test1()).start();

使用匿名内部类的方式实现:

new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    System.out.println("线程");
                }
            }
        }).start();

Thread类的常用方法

  • public String getName() :获取当前线程名称。
  • public void start() :导致此线程开始执行; Java虚拟机调用此线程的run方法。
  • public void run() :此线程要执行的任务在此处定义代码。
  • public static void sleep(long millis) :使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。
  • public static Thread currentThread() :返回对当前正在执行的线程对象的引用。

多线程原理:

?当执行线程的任务结束了,线程自动在栈内存中释放了。但是当所有的执行线程都结束了,那么进程就结束了。

实现Runnable接口比继承Thread类所具有的优势
1. 适合多个相同的程序代码的线程去共享同一个资源。
2. 可以避免java中的单继承的局限性。
3. 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。
4. 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。

线程安全问题(同步)

示例代码:(模拟卖票:同时开启三个线程)

public class Mythread  extends Thread{
    public Mythread() {
    }
    public Mythread(String name) {
        super(name);
    }
    private int num=100;
    @Override
    public void run() {
       while (true){
           
           if(num>0){
         try {
               Thread.sleep(10);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
               System.out.println(getName()+":"+num);
               num--;
           }
       }
    }
}

问题分析:

1、售出3张100 :线程执行if后会进入休眠,放弃cpu的使用权,替他的线程会抢占资源

2、出现1、0、-1的情况:线程唤醒后(已经进入了if语句体),直接输出num--的数据

同步代码块

同步锁:对象锁,多个对象要是有同一把锁(类似于 一把钥匙)(在run方法外定义)

public class Mythread  extends Thread{
    private static int num=100;//共享资源 需要定义为静态资源
   //将同步锁 设定为成员属性 建立对象时,将object赋值给它(以保证 多个线程使用一把同步锁)
   private Object object;
    public Mythread() {
    }
    public Mythread(String name ,Object object) {
        super(name);
        this.object=object;
    }
    @Override
    public void run() {
       while (true){
           synchronized (object){
               if(num>0){
                   try {
                       Thread.sleep(10);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   System.out.println(getName()+":"+num);
                   num--;
               }
           }
       }
    }
}

测试代码:

 public static void main(String[] args) {
        Object o = new Object();
        new Mythread("售票口1",o).start();
        new Mythread("售票口2",o).start();
        new Mythread("售票口3",o).start();
    }

同步方法

同步锁是谁?
对于非static方法,同步锁就是this。
对于static方法,我们使用当前方法所在类的字节码对象(类名.class)。

将可能会存在线程安全问题的代码抽取到方法中

注意:同步锁是this,所以最好使用实现接口的方式创建线程给Thread传入的Runnable接口实现类对象必须一样

示例代码:

public class test1 implements Runnable{
    private static int num=100;
    @Override
    public void run() {
        while (true){
            method();
        }
    }
    public synchronized void method(){
        if(num>0){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+":"+num);
            num--;
        }
    }

}

测试代码:

public static void main(String[] args) {
        test1 test1 = new test1();
        new Thread(test1,"A").start();
        new Thread(test1,"B").start();
        new Thread(test1,"C").start();
        new Thread(test1,"D").start();
    }

Lock锁

同步锁:默认是this

因为同步锁是this,所以最好使用实现接口的方式创建线程

相关方法:

  • public void lock() :加同步锁。
  • public void unlock() :释放同步锁。
public class test1 implements Runnable{
    private static int num=100;
    Lock lock=new ReentrantLock();
    @Override
    public void run() {
        while (true){
            lock.lock();
            if(num>0){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+":"+num);
                num--;
            }
            lock.unlock();
        }
    }
}

线程状态

NEW:新建?????????????????RUNNABLE:可运行? ? ? ? ? ? ? ? BLOCKED:阻塞? ? ? ? ? ? ? ? ?WAITING:无限等待? ? ? ? ? ? ? ? TIMED_WAITING:计时等待? ? ? ? ? ? ? ? TERMINATED:被终止

TIMED_WAITING:计时等待

方法一:Thread.sleep(10)

方法二:Object.wait(毫秒值)(时间一到,自动唤醒)

Waiting(无限等待)

Object.wait:无限等待(只能等待唤醒)

Object.notify()/Object.notifyAll():唤醒单个或多个线程

示例代码(生产者、消费者) 两个线程必须使用同一把锁

 public static void main(String[] args) {
        Object o=new Object();//同步锁
        //消费者
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    synchronized (o){
                System.out.println(Thread.currentThread().getName()+"点餐");
                        try {
                            o.wait();//无限等待
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("吃完了");
                    }
            }}
        }).start();
        //生产者
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    try {
                        Thread.sleep(5000);//作用让消费者先点餐
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (o){
                        System.out.println("做好了");
                        o.notify();//唤醒等待线程
                    }
                }
            }
        }).start();
    }

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-08-28 08:53:50  更:2021-08-28 08:55:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 12:53:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码