Java学习 | 多线程基础

1.进程、线程简介

1.1进程

进程(process):是程序的一次执行过程,或是正在运行的一个程序。动态过程:有它自身的产生、存在和消亡的过程。

1.2线程

线程(thread):进程可进一步细化为线程,是一个程序内部的一条执行路径

1.3线程分类

  • 守护进程
  • 用户进程
    当一个用户线程结束后,JVM会检查系统中是否还存在其他用户线程,如果只剩下守护线程而没有用户线程的话,JVM就会终止。

2.创建多线程方法

2.1继承的方法

  • 创建一个线程类,继承自Thread
  • 实现run()方法
  • 创建一个该线程类的对象
  • 调用start()方法启动线程,并执行run()方法
public class TestThread {
	public static void main(String[] args) {		
		MyThread my1 = new MyThread();
		// 一个线程只能启动一次;start()方法步骤是:启动线程;调用run()方法;
		my1.start();
		for(int i = 0; i < 100; i++) {
			System.out.println(Thread.currentThread().getName() + ": " + i);
		}
	}
}
// 继承的方法创建多线程
class MyThread extends Thread{
	@Override
	public void run() {
		for(int i = 0; i < 100; i++) {
			System.out.println(Thread.currentThread().getName() + ": " + i);
		}
	}
}

2.2实现的方法

  • 创建一个实现Runnable接口的类
  • 实现run()方法
  • 创建一个Runnable接口实现类的对象
  • 将此对象作为形参传递给Thread类构造器中,创建Thread类的对象,此对象为一个线程
  • 调用start()方法启动线程,并执行run()方法
public class TestThreadRunnable {
	public static void main(String[] args) {		
		MyThreadRunnable my1 = new MyThreadRunnable();
		// 要启动线程必须使用start()方法	
		Thread t1 = new Thread(my1);
		t1.start();
	}
}
// 实现的方法创建多线程
class MyThreadRunnable implements Runnable{
	@Override
	public void run() {
		for(int i = 0; i < 100; i++) {
			System.out.println(Thread.currentThread().getName() + ": " + i);
		}
	}
}

2.3两种方式比较

实现的方式较优

  • 避免Java单继承的局限性
  • 如果多个线程要操作同一份资源,更适合使用实现的方式

3.Thread类的常用方法

方法名功能
start()启动线程并执行相应的run()方法
run()子线程要执行的代码放入run()方法中
currentThread()静态的,调取当前的线程
getName()获取此线程的名字
setName()设置此线程的名字
yield()调用此方法的线程释放当前CPU的执行权
join()在A线程中调用B线程的join()方法,表示,当执行到此方法,A线程停止执行,执行完B线程,A线程再接着执行
isAlive()判断当前线程是否存活
sleep(long l)显式的让当前线程睡眠l毫秒

4.线程的调度

4.1调度策略

  • 时间片
  • 抢占式:高优先级的线程抢占CPU

4.2调度方法

  • 同优先级线程组成先进先出队列,使用时间片策略
  • 对高优先级,使用优先调度的抢占式策略

4.3线程的优先级

  • 线程优先级范围:1 ~ 10
  • getPriority():返回线程优先值
  • setPriority(int newPriority):改变线程的优先级
  • 线程创建时继承父线程的优先级

5.线程的生命周期

如图,线程的声明周期分为五种状态:
在这里插入图片描述

6.线程的同步机制(synchronized)

  • 要求:所有的线程必须共用同一把锁
  • 注意:在实现的方式中,考虑同步的话,可以使用this来充当锁,而继承的方式不允许这样
  • 对于静态方法而言,使用当前类本身充当锁(反射)

6.1同步代码块

Object obj = new Object();
synchronized(obj/*同步监视器*/){    //(---->实现的方法创建多线程时,这里可以填this)
    // 需要被同步的代码块(即为操作共享数据的代码)
    // 同步监视器:由任何一个类的对象来充当,哪个线程获取此监视器,谁就执行大括号里被同步的代码。俗称:锁。
}

6.2同步方法

同步方法锁:this(创建线程的方法为实现时 才成立)

public synchronized void show(){
    .....
}

6.3同步方法解决单例模式之懒汉式的线程安全问题

class Singleton{

    private Singleton(){}
    private static Singleton instance = null;
    public static Singleton getInstance(){
        if(instance == null){
            synchronized(Singleton.class){
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

7.线程的通信

定义在Object类里面

  • wait():令当前线程挂起并放弃CPU、同步资源,使别的线程可访问并修改共享资源,而当前线程排队等候再次对资源的访问(释放锁)
  • notify():唤醒正在排队等待同步资源的线程中优先级最高者结束等待
  • notifyAll():唤醒全部
  • 此三个方法只有在同步代码块或者同步方法中才能使用,否则会抛出异常

8.生产者与消费者的问题

public class TestProduceConsume {
	public static void main(String[] args) {
		Clerk clerk = new Clerk();
		Prodecer p1 = new Prodecer(clerk);
		Consumer c1 = new Consumer(clerk);
		
		Thread t1 = new Thread(p1);
		Thread t2 = new Thread(c1);
		
		t1.setName("生产者线程");
		t2.setName("消费者线程");
		
		t1.start();
		t2.start();
		
	}

}

class Clerk{
	// 产品数量
	private int product;
	// 生产产品
	public synchronized void addProduct() {
		if(product >= 20) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}else {
			product++;
			System.out.println(Thread.currentThread().getName() + ": 生产了第 " + product + " 个产品");
			notify();
		}
	}
	// 消费产品
	public synchronized void useProduct() {
		if(product <= 0) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}else {
			System.out.println(Thread.currentThread().getName() + ":" + "消费了第 " + product + "个产品");
			product--;
			notify();
		}
	}
}
// 生产者类
class Prodecer implements Runnable{
	private Clerk clerk;
	
	public Prodecer(Clerk clerk) {
		super();
		this.clerk = clerk;
	}

	@Override
	public void run() {
		System.out.println("生产者开始生产产品");
		while(true) {
			try {
				Thread.currentThread().sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			clerk.addProduct();
		}
	}
}
// 消费者类
class Consumer implements Runnable{
	private Clerk clerk;
	
	public Consumer(Clerk clerk) {
		super();
		this.clerk = clerk;
	}

	@Override
	public void run() {
		System.out.println("生产者开始生产产品");
		while(true) {
			try {
				Thread.currentThread().sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			clerk.useProduct();
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值