线程的概念
▪ 程序:Program,是一个指令的集合
▪ 进程:Process,(正在执行中的程序)是一个静态的概念 进程是程序的一次静态态执行过程, 占用特定的地址空间. 每个进程都是独立的,由3部分组成cpu,data,code
缺点:内存的浪费,cpu的负担
▪ 线程:是进程中一个“单一的连续控制流程”(a single sThread,equential flow of control)/执行路径
线程又被称为轻量级进程(lightweight process)。
Threads run at the same time, independently of one another
一个迚程可拥有多个并行的(concurrent)线程
一个迚程中的线程共享相同的内存单元/内存地址空间
可以访问相同的 变量和对象,而且它们从同一堆中分配对象 --> 通信、数据交换、同步操作
由于线程间的通信是在同一地址空间上进行的,所以不需要额外的通信 机制,这就使得通信更简便而且信息传递的速度也更快
进程与线程
▪ 一个进程中至少有一个线程
• Java虚拟机启动的时候会有一个进程java.exe,该进程中 至少有一个线程,在负责java程序的执行。而且这个线程 运行的代码存在于main方法中,该线程称之为主线程。
• 一个进程中的线程共享代码和数据空间
• 线程结束 进程未毕结束,但进程结束,线程一定结束 。
• 进程中包含线程,线程是进程的一部分
JAVA中实现多线程(一)
▪ 在Java中负责线程的这个功能的是Java.lang.Thread 这个类
▪ 可以通过创建 Thread 的实例来创建新的线程。
▪ 每个线程都是通过某个特定Thread对象所对应的方法run( )来完 成其操作的,方法run( )称为线程体。
▪ 通过调用Thead类的start()方法来启动一个线程。
创建线程的方式一 继承Thread类
操作步骤: 【1】继承Thread类 【2】重写run方法 【3】创建对象, 调用start()方法 启动线程。
public class ThreadDemo01 extends Thread {
//重写父为的run方法
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println("第"+i+"次threadrun........");
}
}
public static void main(String[] args) {
//创建对象,就创建好一个线程
ThreadDemo01 d=new ThreadDemo01();
//d.run();//启动线程使用start方法
d.start();
for(int i=0;i<5,i++);
System.out.println("main-->"+i);
}
}
}
创建线程的方式二实现Runnable接口
操作步骤: 【1】实现Runnable接口 【2】重写run方法 【3】创建对象, 调用start()方法 启动线程
public class RunableDemo implements Runnable { @Override public void run() { for(int i=0;i<10;i++){ System.out.println("第"+i+"次threadrun........"); } } public static void main(String[] args) { //创建对象,就创建好一个线程 RunableDemo rd=new RunableDemo(); Thread t=new Thread(rd); t.start(); for(int i=0;i<5;i++){ System.out.println("main-->"+i); } } }
JAVA中实现多线程(二)
▪ 继承Thread类方式的缺点:那就是如果我们的类已经从一个类继承(如小程序必须继承自 Applet 类),则无法再继承 Thread 类
▪ 通过Runnable接口实现多线程 优点:可以同时实现继承。实现Runnable接口方式要通用一些。
▪ (1)避免单继承
▪( 2)方便共享资源 同一份资源 多个代理访问。
线程状态
阻塞状态(sleep/yield/join方法)
有三种方法可以暂停Thread执行:
1. sleep:会释放锁,Sleep时别的线程也丌可以访问锁定对象。
2. yield:让出CPU的使用权,从运行态直接迚入就绪态。让CPU重新挑选哪一个线程迚入运行状态。
3. join:当某个线程等待另一个线程执行结束后,才继续执行时,使调用该方法的线程在此之前执行完毕,也就是等待调用该方法的线程执行完毕后再往下继续执行
使用同步解决线程的安全性问题
同步的前提:
(1)必须有两个或两个以上的线程
(2)必须是多个线程使用j同一资源
(3)必须保证同步中只能有一个线程在运行
package producerAndConsumer;
//生产者和消费者共享的资源:商品
public class Goods {
private String brand;
private String name;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//消费者从共享区域中去商品(拿走商品)
public class Consumer implements Runnable {
private Goods goods;
public Consumer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("消费者消费了==========="+goods.getBrand()+"========="+goods.getName());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//生产者负责生产商品
public class Producer implements Runnable {
private Goods goods;
public Producer(Goods goods){
this.goods = goods;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
//交替生产娃哈哈矿泉水和旺仔小馒头
if(i % 2 == 0){
goods.setBrand("娃哈哈");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
goods.setName("矿泉水");
}else{
goods.setBrand("旺仔");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
goods.setName("小馒头");
}
System.out.println("生产者生产了---------" + goods.getBrand() +"-----"+goods.getName());
}
}
}
/*
测试类
出现问题:
1.生产者未生产,消费者已经消费了;
2.连续生产连续消费;
3.商品的两个属性,品牌和名称不能正确的对应。
*/
public class Test1 {
public static void main(String[] args) {
Goods goods = new Goods();
Producer producer = new Producer(goods);
Consumer consumer = new Consumer(goods);
Thread t1 = new Thread(producer);
Thread t2 = new Thread(consumer);
t1.start();
t2.start();
}
}
第二种
// 消费者从共享区域中取商品(拿走商品)
public class Consumer implements Runnable {
private Goods goods;
public Consumer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
goods.get();
}
}
}
public class Goods {
private String brand;
private String name;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//生产商品的方法
public synchronized void set(String brand,String name){
this.setBrand(brand);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.setName(name);
System.out.println("生产者生产了*******************"+this.getBrand()+"*******"+this.getName());
}
//消费商品的方法
public synchronized void get(){
System.out.println("消费者消费了======"+this.getBrand()+"======="+this.getName());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//生产者负责生产商品
public class Producer implements Runnable {
private Goods goods;
public Producer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
//交替生产娃哈哈矿泉水和旺仔小馒头
if(i%2==0){
goods.set("娃哈哈","矿泉水");
}else{
goods.set("旺仔","小馒头");
}
}
}
}
public class Test1 {
public static void main(String[] args) {
Goods goods = new Goods();
Producer producer = new Producer(goods);
Consumer consumer = new Consumer(goods);
Thread thread = new Thread(producer);
Thread thread1 = new Thread(consumer);
thread.start();
thread1.start();
}
}
三
public class Consumer implements Runnable {
private Goods goods;
public Consumer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
goods.get();
}
}
}
//生产者和消费者的共享资源:商品
public class Goods {
private String brand;
private String name;
//定义一个标识位,来表示共享区域中是否存在商品
private boolean isFull;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//生产商品的方法
public synchronized void set(String brand,String name){
/*
如果生产者线程获取对应cpu资源,得到了执行机会,此时先判断共享区域中是否存在商品,如果已经存在了,那么当前生产者线程
进入阻塞状态,等待消费者来消费,反之如果共享区域中不存在商品,那么生产商品就可以了。
*/
if(isFull) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.setBrand(brand);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.setName(name);
System.out.println("生产者生产了*************"+this.getBrand()+"****"+this.getName());
//如果程序能执行到此处,说明已经生产商品完毕了,此时需要标志位为true
isFull = true;
//唤醒消费者前来消费
notify();
}
//消费商品的方法
public synchronized void get(){
/*
如果消费者线程获取到对应的cpu时间片,获取到了执行机会了,此时先判断共享区域中是否存在商品,如果不存在商品,当前真正执行的消费者
线程进入阻塞状态,等待生产者生产商品,反之如果已经存在商品,那么消费者直接消费就可以了。
*/
if(!isFull){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费者消费了========="+this.getBrand()+"===="+this.getName());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//如果程序运行到此处,说明消费者已经消费完毕,需要修改标志位为false
isFull = false;
//唤醒生产者生产商品
notify();
}
}
package producerAndConsumer3;
//生产者生产商品
public class Producer implements Runnable {
private Goods goods;
public Producer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
//交替生产娃哈哈矿泉水和旺仔小馒头
if(i%2==0){
goods.set("娃哈哈","矿泉水");
}else {
goods.set("旺仔","小馒头");
}
}
}
}
package producerAndConsumer3;
/*
测试类
出现问题:
1、生产者未生产,消费者已经消费了;
2、连续生产连续消费;
3、商品的两个属性,品牌和名称不能正确的对应。----解决了,使用同步方法解决的
*/
public class Test1 {
public static void main(String[] args) {
Goods goods = new Goods();
Producer producer = new Producer(goods);
Consumer consumer = new Consumer(goods);
Thread t1 = new Thread(producer);
Thread t2 = new Thread(consumer);
t1.start();
t2.start();
}
}
四
package producerAndConsumer4;
//消费者队列
import java.util.concurrent.BlockingQueue;
public class ConsumerQueue implements Runnable {
private BlockingQueue<Goods> blockingQueue;
public ConsumerQueue(BlockingQueue<Goods> blockingQueue) {
this.blockingQueue = blockingQueue;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
Goods goods = null;
try {
goods = blockingQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("消费者消费了商品==========" + goods.getBrand() + "=========" +goods.getName());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package producerAndConsumer4;
//
public class Goods {
private String brand;
private String name;
public Goods() {
}
public Goods(String brand, String name) {
this.brand = brand;
this.name = name;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package producerAndConsumer4;
import java.util.concurrent.BlockingQueue;
//生产者生产
public class ProducerQueue implements Runnable {
//阻塞式队列
private BlockingQueue<Goods> blockingQueue;
public ProducerQueue(BlockingQueue<Goods> blockingQueue) {
this.blockingQueue = blockingQueue;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
Goods goods = null;
if(i % 2 == 0){
goods = new Goods("娃哈哈","矿泉水");
}else{
goods = new Goods("旺仔","小馒头");
}
System.out.println("生产者生产了商品--------" +goods.getBrand() + "----" + goods.getName());
//把生产者生产的商品放入到队列中存储
try {
blockingQueue.put(goods);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package producerAndConsumer4;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Test {
public static void main(String[] args) {
BlockingQueue <Goods> blockingQueue = new ArrayBlockingQueue<Goods>(5);
ProducerQueue producerQueue = new ProducerQueue(blockingQueue);
ConsumerQueue consumerQueue = new ConsumerQueue(blockingQueue);
new Thread(producerQueue).start();
new Thread(consumerQueue).start();
}
}