二十、多进程

1.进程:

I. 运行时的程序,称为进程。
II. 单核CPU在任一时间点上,只能运行一个进程。
III. 宏观并行、微观串行
IV. cpu get NumberOfCores 获得核心数

2.线程:

I. 轻量级进程
II. 程序中的一个顺序控制流程,也是CPU的基本调度单位。
III. 进程可以由单个或多个线程组成,彼此间完成不同的工作,交替执行,称为多线程
IV. JVM虚拟机是一个进程,默认包含主线程(Main函数),可以通过代码创建多个独立线程,与Main线程并发执行。

3.线程的组成:

I.CPU时间片
II. 运行数据:
(1).堆空间:存储线程需要使用的对象,多个线程可以共享堆中的对象
(2).栈空间:存储线程需要使用的局部变量,每个线程都拥有独立的栈

4. 线程的创建:

I. 继承Thread类,自定义类变成线程类
II. 实现Runnable接口,赋予自定义类线程任务的能力。
III. 实现Runnable接口,不影响类继承,更灵活。
IV. 线程创建后,需要调用start();方法,来启动线程,由JVM调用run()方法。直接调用run()方法并不是线程的启动。

MyThread t1 = new MyThread();
		t1.start();
		
MyRunnable mr = new MyRunnable();
		Thread t2 = new Thread(mr);
		t2.start();
		
class MyThread extends Thread{
	public void run() {
		for(int i = 1;i<=50;i++) {
			System.out.println(Thread.currentThread().getName()+"-"+i);
		}
	}
}

class MyRunnable implements Runnable{
	@Override
	public void run() {
		for(int i = 1;i<=50;i++) {
			System.out.println("MyRunnable -"+i);
		}
	}	
}

5.线程的状态:

在这里插入图片描述

6. 线程常见方法:

I. 休眠 sleep(long millis);
(1).当前线程主动休眠 millis毫秒,进入有限期等待!
II. 放弃 yield();
(1).当前线程主动放弃时间片,回到就绪状态,竞争下一次时间片
III. 结合 join();
(1).允许其他线程加入到当前线程中,当前线程进入无限期等待!
//t1.join() 等待t1执行完后,才能重新恢复就绪状态

在这里插入图片描述

8. 线程安全的问题:

I. 当多线程并发访问临界资源时,如果破坏了原子操作,可能会导致数据不一致。
II. 临界资源:共享资源(同一对象、堆空间),一次仅允许一个线程使用,才可保证其正确性
III.原子操作:不可分割的多步操作,被视作为一个整体,其顺序和步骤不能打乱或缺省。

9. synchronized 同步锁:

I.每个对象都有一个互斥锁标记,用来分配给线程。
II.只有持有对象互斥锁标记的线程,才能进入对该对象加锁的同步操作中(同步方法、同步代码块)。
III.只有线程退出同步操作时,才会释放相应的锁标记

10. 同步方式:

10、同步方式
I.同步代码块
(1). synchronized(临界资源对象){
//原子操作
}
II. 同步方法
(1) . synchronized 返回值类型 方法名成(参数列表){
//原子操作
}

11.线程的状态:

在这里插入图片描述

12. 同步规则:

I. 只有在调用包含同步代码块的方法或者是同步方法时,才需要对象的锁标记
II. 如果调用的是不包含同步代码块的方法或普通方法时,则不需要锁标记,直接调用即可。
III. 已知线程安全的内容:StringBuffer、Vector、Hashtable(定义的方法加了synchronize)

13. 死锁、生产者与消费者:

public class TestCustomer {

	public static void main(String[] args) {
		Shop shop = new Shop();
		Thread p = new Thread(new Product(shop),"生产者");
		Thread c = new Thread(new Customer(shop),"消费者");
		p.start();
		c.start();
	}
}
//商品
class Goods{
	private int id;
	public Goods(int id) {
		this.id = id;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
}
//商店
class Shop{
	Goods goods;
	boolean flag;
	//生产者调用的方法
	public synchronized void saveGoods(Goods goods) throws InterruptedException {
		//1.判断商品是否充足
		if(flag == true) { //商品充足
			this.wait(); //商品充足,进入等待状态
		}
		System.out.println(Thread.currentThread().getName()+"生产并在商场里存放了"+goods.getId()+"件商品");
		this.goods = goods;
		flag = true;
		this.notifyAll();
	}
	//消费者调用的方法
	public synchronized void buyGoods() throws InterruptedException {
		if(flag == false) {
			this.wait(); //消费者进入等待队列
		}
		 System.out.println(Thread.currentThread().getName()+"购买了"+goods.getId()+"件商品");
		 this.goods = null;
		 flag = false;
		 this.notifyAll();
	}
}
//生产者
class Product implements Runnable{
	Shop shop;
	public Product(Shop shop) {
		this.shop = shop;
	}
	@Override
	public void run() {
		for(int i = 1;i<20;i++) {
			try {
				shop.saveGoods(new Goods(i));
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}	
}

class Customer implements Runnable{
	Shop shop;
	public Customer(Shop shop) {
		this.shop = shop;
	}
	@Override
	public void run() {
		for(int i = 1;i<20;i++) {
			try {
				shop.buyGoods();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}	
}

14. 线程通信:

I. 等待
(1) wait();
(2) 必须在对obj(对象)加锁的同步代码块(或同步方法)中,在一个线程执行期间,调用了obj.wait(),该线程会释放所拥有的锁标记。同时,进入到obj的等待队列中。等待唤醒
II. 通知(唤醒)
(1).notify();、notifyAll();
(2).必须在对obj加锁的同步代码块(或同步方法)中,从obj的Waiting(等待队列)中随机释放一个或全部线程。对自身线程无影响。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值