• 多线程的创建、线程的状态和调度and同步、join和yield以及单例设计模式的种类


    创建线程方式 重要

    ​ 继承Thead

    ​ 实现Runnable接口,重写run方法

    package com.qfedu.thread;
    
    /**
     * 实现Runnable接口,重写run()方法
     * @author renrui
     *
     */
    public class MyRunnable implements Runnable {
    
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		for(int i = 0; i < 100; i++) {
    			System.out.println(Thread.currentThread().getName() + ":" + i);
    		}
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    package com.qfedu.thread;
    
    public class App {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		
    		// 使用线程,推荐通过实现Runnable接口方式
    		MyRunnable myRunnable = new MyRunnable();
    		
    		// 创建线程
    		Thread t1 = new Thread(myRunnable);
    		// 获取优先级 默认优先级5
    		System.out.println(t1.getPriority());
    		// 设置优先级 1-10
    		// t1.setPriority(10);
    		t1.setPriority(Thread.MAX_PRIORITY);
    		
    		Thread t2 = new Thread(myRunnable);
    		// 启动线程
    		t1.start();
    		t2.start();
    		
    		// 使用匿名内部类
    		Thread t3 = new Thread(new Runnable() {
    			
    			@Override
    			public void run() {
    				// TODO Auto-generated method stub
    				for(int i = 0; i < 100; i++) {
    					System.out.println(Thread.currentThread().getName() + ":" + i);
    				}
    			}
    		});
    		t3.start();
    		
    		
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    java中线程的状态 重要

    6状态

    1)新建状态new: 调用new 创建对象

    2)可运行状态runnable: 调用start(),进入可运行状态,可以认为可运行状态中包含就绪和运行两个状态

    3)阻塞状态blocking:某个线程调用同步方法,还没有释放锁时,其他线程也访问该方法,进行阻塞状态。当线程执行完毕释放锁,那些阻塞的线程进入可运行状态

    4)等待状态waiting:调用wait()/join()等方法后,线程进入等待状态。当join对应的线程执行完毕,或者wait()的线程被唤醒,等待的线程进入可运行状态

    5)计时等待状态time waiting: 和等待状态类型,调用sleep(long)/wait(long)/join(long)等方法,进入计时等待状态

    6)终止状态terminated:run方法执行完毕,或者线程异常,进入终止状态

    线程的调度

    sleep 线程睡眠

    ​ 某个线程中调用sleep方法,该线程睡眠,进入计时等待状态

    package com.qfedu.sleep;
    
    public class App {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    
    		MyThread t = new MyThread();
    		t.start();
    		
    		try {
    			// 受检异常
    			// 线程睡眠 参数表示睡眠时间 单位毫秒
    			// main方法中调用sleep,主线程休眠
    			Thread.sleep(10);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    		for(int i = 0; i < 100; i++) {
    			System.out.println(Thread.currentThread().getName() + ":" + i);
    		}
    		
    	}
    
    }
    
    class MyThread extends Thread {
    	
    	@Override
    	public void run() {
    		try {
    			Thread.sleep(20);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		for(int i = 0; i < 100; i++) {
    			System.out.println(Thread.currentThread().getName() + ":" + i);
    		}
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    join 了解

    ​ 线程插入 A 线程中,调用B.join() B线程就会插队,B线程执行完,执行其他线程逻辑

    package com.qfedu.join;
    
    public class App {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    
    		MyThread t = new MyThread();
    		t.start();
    		
    		for(int i = 0; i < 500; i++) {
    			
    			if(i == 20) {
    				try {
    					// 线程插队
    					// main方法中调用join方法的,main主线程进入等待状态
    					// t线程插队,插队的线程执行完毕,等待的线程才会继续执行
    					// t.join();
    					
    					// 线程插队时,指定一个时间,单位毫秒
    					// 插队的线程执行完毕,或者插队时间到,等待的线程进入可运行状态
    					// main和t共同竞争cpu资源
    					t.join(1);
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    			
    			System.out.println(Thread.currentThread().getName() + ":" + i);
    		}
    		
    	}
    
    }
    
    class MyThread extends Thread {
    	
    	@Override
    	public void run() {
    		for(int i = 0; i < 500; i++) {
    			System.out.println(Thread.currentThread().getName() + ":" + i);
    		}
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    yield 了解

    ​ 线程礼让,某个线程中调用yield方法,该线程进入就绪状态

    package com.qfedu.yield;
    
    public class App {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Product p = new Product();
    		Customer c = new Customer();
    		
    		p.start();
    		c.start();
    	}
    
    }
    
    class Product extends Thread {
    	@Override
    	public void run() {
    		for(int i = 0; i < 100; i++) {
    			if(i == 8) {
    				// 调用yield方法之前,线程之间是竞争关系
    				// 线程礼让
    				// 调用礼让方法的线程进入就绪状态
    				// 和其他线程一起竞争cpu资源
    				Thread.yield();
    			}
    			System.out.println(Thread.currentThread().getName() + ":" + i);
    		}
    	}
    }
    
    class Customer extends Thread {
    	@Override
    	public void run() {
    		for(int i = 0; i < 100; i++) {
    			System.out.println(Thread.currentThread().getName() + ":" + i);
    		}
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    线程同步 重要

    ​ 主要为了解决线程安全的问题

    ​ 多个线程访问线程共享的数据时 ,要注意线程安全问题

    ​ 课件中,使用同步机制,实现线程同步

    ​ 同步代码块

    ​ synchronized(锁对象) {}

    ​ 同步方法

    ​ synchronized 返回值 方法名(参数) {}

    ​ 注意:锁对象需要唯一,多个需要共享一把锁

    package com.qfedu.syn;
    
    public class App {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Ticket ticket = new Ticket();
    		
    		// 启动了50个线程
    		for(int i = 0; i < 50; i++) {
    			Thread t = new Thread(ticket);
    			t.start();
    		}
    	}
    
    }
    
    class Ticket implements Runnable {
    	// 初始有100张票
    	// 50个线程共享num
    	private int num = 100;
    	
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    //		num--;
    //		System.out.println("剩余票数:" + num);
    		
    		// 调用同步方法
    		// A线程先抢到cpu资源,执行同步方法,加锁,
    		// A线程执行代码的过程中,失去cpu的控制权(调度系统将cpu分配给其他线程),B线程抢到cpu,执行同步方法
    		// B执行同步方法时,A线程还没有执行完代码,锁依旧存在,B就会阻塞,等着A释放锁
    		// A释放锁后,其他阻塞的线程进入就绪状态,哪个线程先抢到cpu,哪个线程就可以执行同步方法,并加锁
    		
    		// 注意:A执行完,释放锁,其他线程,比如BCDEF等线程,还需要抢占cpu资源,而不是B先执行
    		// 阻塞的线程会在“锁池”中记录(了解)
    		// show();
    		
    		// 同步代码块
    		// 基本语法:synchronized(代表锁的对象) {执行的逻辑}
    		// 50个线程共用一个ticket对象,this表示当前的ticket对象,所以this可作为多个线程公用的锁
    		synchronized (this) {
    		// synchronized (Ticket.class) {  // 该写法了解一下 Ticket.class表示获取Ticket的Class对象
    			num--;
    			System.out.println(Thread.currentThread().getName() + ",剩余票数:" + num);
    		}
    		
    	}
    	
    	// 同步方法,在代码中“锁”也是对象,同步方法中,使用的锁是this对象
    	public synchronized void show() {
    		num--;
    		System.out.println(Thread.currentThread().getName() + ",剩余票数:" + num);
    	}
    	
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    单例设计模式 次重要

    ​ 某个类,在整个程序中只能有一个对象的时候,就可以使用单例模式

    懒汉式

    package com.qfedu.singleton;
    
    /**
     * 懒汉式 考虑多线程环境的线程安全问题
     * @author renrui
     *
     */
    public class Singleton {
    	private static Singleton singleton = null;
    	
    	// 构造方法设置成私有的,类外不能通过new 创建对象
    	private Singleton() {}
    	
    	// 在类内部创建对象
    	public static synchronized Singleton getInstance() {
    		if(singleton == null) {
    			singleton = new Singleton();
    			return singleton;
    		} else {
    			return singleton;
    		}
    		
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    饿汉式

    package com.qfedu.singleton;
    
    /**
     * 饿汉式 推荐
     * @author renrui
     *
     */
    public class Singleton2 {
    	
    	// 类加载的时候创建静态变量,只会执行一次
    	// 定义静态变量,直接创建对象并赋值
    	private static Singleton2 singleton2 = new Singleton2();
    
    	private Singleton2() {}
    	
    	public static Singleton2 getInstance() {
    		return singleton2;
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
  • 相关阅读:
    UI设计原则背后的认知心理学 优漫动游
    YDOOK:onnx onnxruntime Python APIs 接口文档网址
    Linux压缩、解压缩以及打包命令
    Elasticsearch实践:ELK+Kafka+Beats对日志收集平台的实现
    python 迭代器
    网安等保-Linux服务器之最新Ubuntu-22.04-LTS系统内核优化与安全加固配置脚本使用分享
    如何发高质量的外链?
    Windows安装Docker Desktop并配置镜像、修改内存占用大小
    字符数组基础知识
    vscode使用docker 简介、步骤
  • 原文地址:https://blog.csdn.net/weixin_51423778/article/details/126777499