多线程_生产者与消费者

13 篇文章 0 订阅
6 篇文章 1 订阅


一. 概念

      进程是指在系统中正在运行的一个应用程序;

    线程是系统分配处理器时间资源的基本单元,或者说进程之内独立执行的一个单元。

    对于操作系统而言其调度单元是线程。一个进程至少包括一个线程,通常将该线程称为主线程。

    一个进程从主线程的执行开始进而创建一个或多个附加线程,就是所谓基于多线程的多任务!!


    线程的状态:
        线程有五种状态:新生状态,可运行状态,运行状态,阻塞状态和运行结束状态

        当一个线程类在创建了对象之后,就意味这一个线程的产生,

        在调用start()方法之前为“新生状态”,调用start()方法让线程进入“可运行状态Runnable”,此时的线程可以被线程管理器调度;

        一旦线程调度(获取到时间片)即从可运行状态进入到“运行状态Running”;

        在运行过程中遇到阻塞事件(如:sleep(),wait(),锁等待……)便使线程变成        了“阻塞状态Blocked”;

        直到阻塞事件消除(如:notify(),锁释放……)线程有由阻塞状态变回“可运行状态”;

        当线程执行结束则为“结束状态”。


join()方法:
     以A,B两个线程为例:如果在线程A中调用B.join()方法,表示让线程A处于等待状态,直到线程B执行结束后才接着执行

sleep()方法:
    sleep()方法时让当前线程处于等待状态,等待时间由参数决定
    sleep()方法的调用形式:Thread.sleep(时间毫秒数);

wait()方法:
    使当前线程进入阻塞状态,直到有notify()方法或者notifyAll()方法唤醒


notify()方法:
    唤醒一个由于wait()方法处于等待的线程


notifyAll()方法:
       唤醒所有由于wait()方法处于等待的线程


调用一个Object的wait与notify/notifyAll的时候,必须保证调用代码对该Object是同步的,

也就是说必须在作用等同于synchronized(obj){......}的内部才能够去调用obj的wait与notify/notifyAll三个方法,否则就会报错:

java.lang.IllegalMonitorStateException:current thread not owner

wait方法和sleep方法都可以让线程等待若干时间,除了wait方法可以唤醒之外,另外一个主要区别是wait方法会释放目标对象的锁,而sleep方法不会释放。


二.创建

    创建一个线程有以下两种方式[可以查阅JDK API]:

    ① 线程类继承Thread,重写run()方法,在run()方法中完成此线程所要完成的工作,直接创建线程类的对象,然后调用start()方法启动线程,默认          调用run()方法。

    ② 线程类实现Runnable接口,实现run()方法,在run()方法中完成此线程所要完成的工作;创建线程的时候要注意:
       首先创建实现Runnable接口的线程类的对象t,然后通过Thread tt = new Thread(t);来创建线程tt。也是通过调用start()方法来启动线程。


    要想创建一个线程类,实质上是必须实现Runnable接口,因为Thread本身也是实现了Runnable接口的[可以点击进入Thread看其具体实现,是实现了Runnable接口的]。


    但是如果要调用start()方法来启动一个线程,就必须构建Thread类的对象:

    如果是用第①中方式创建的线程类,那么他所创建的对象就可以隐式转换成Thread对象,所以可以直接调用start()方法;

    如果使用第②种方式创建的线程类,那么使用这个线程类创建对象之后,还必须通过这个对象创建一个Thread类的对象。


    守护线程:
         如何设置成守护线程:setDeamon(true);
         守护线程一般用来为其他的线程提供服务,当其他的线程全部执行完毕以后,无论守护线程是否执行完成都会自动终止。

    线程优先级:
         优先级范围:1—10
         设置线程t优先级的方法:t.setPriority(1--10)
         获取线程t优先级的方法:t.getPriority()
         线程优先级的默认值是:5
         线程优先级为10的优先级最高,为1的最低


下面是一个生产者与消费者的示例,加深对多线程的理解与运用!!!

package com.thread.src;

public class Test {
	public static void main(String[] args) {
		
		//工具类
		Utils u = new Utils();
		
		//创建一个生产者线程
		Productor p = new Productor(u);
		//创建一个消费者线程
		Customer c = new Customer(u);
		
		//启动生产者和消费者线程 
		p.start();
		c.start();
	}
}

package com.thread.src;
/**
 * 生产者
 * @author winy_lm
 *
 */
public class Productor extends Thread{
	//工具类
	private Utils u;
	//构造函数
	public Productor(Utils u){
		this.u = u;
	}

	//线程执行方法
	public void run(){
		while(true){
			//每循环一次向data中放一个数据
			//调用Utils类中的procuce()方法来生产
			u.produce();
		}
	}
}

package com.thread.src;
/**
 * 消费者
 * @author winy_lm
 *
 */
public class Customer extends Thread{
	//工具类
	private Utils u;
	//构造函数
	public Customer(Utils u){
		this.u = u;
	}
	
	//线程执行方法
	public void run(){
		while(true){
			//每次从data中取一个数据
			u.consume();
		}
	}
}

package com.thread.src;

/**
 * 工具类
 * @author winy_lm
 *
 */
public class Utils {

	//被操作的数组,最多只能放三个,超过三个就等待,为0个的时候也等待
	private int[] data = new int[3];
	// 定义一个count用来标识data数据的个数
	private int count = 0;
	// 定义一个num用来表示,生产者上一次生产的数据
	private int num = 0;

	/*
	 * 如果一个类中的方法同时被2个或者多个线程访问, 那么我们就要把这个/这些方法同步,避免破坏数据完整性
	 */

	/**
	 * 此方法是完成生产向data放数据的功能
	 */
	synchronized public void produce() {
		try {
			if (count < 3) {
				data[count] = num + 1;
				System.out.println("生产者:" + (num + 1));
				num = num + 1;
				count++;
				// 生产者生产数据之后 data中有数据了,消费者可以消费了
				// 所以要唤醒消费者
				notifyAll();
			} else {
				//等待被唤醒
				wait();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 此方法用来供消费者线程调用,消费一个数据
	 */
	synchronized public void consume() {
		try {
			if (count > 0) {
				int m = data[count - 1];
				data[count - 1] = 0;
				count--;
				System.out.println("消费者:" + m);
				// 因为我们已经消费了一个数据,data有空位,可以生产了
				// 所以我们调用notifyAll()来唤醒生产者生产
				notifyAll();
			} else {
				// else表明data中是空的,消费者不能消费,只有等待生产者生产
				//等待被唤醒
				wait();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}



关于多线程,这里有篇很全面很详细的文章可以参考下:

点击这里





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值