线程的两种实现方式,以及区别

让类成为线程类有两种方式,实现Runnable接口,以及继承Thread类(类中实现了Runnable接口,还提供了一些额外的方法)。

一、Runnable相对优势:

1、java的单继承,当继承了Thread类,则不能继承其他类,而实现Runnable接口可以
2、实现Runnable接口的线程类的多个线程,可以访问同一变量,而Thread则不能(多窗口买票问题)

原因:两种方式启动方式不同:

Runnable线程类是实例化一个对象o之后,通过多次new Thread(o).start();启动多个线程,而这几个线程属于一个对象,对象的成员变量是同一个。

Thread线程类启动多个线程需要 new MyThread().start();每个线程启动都对应多个对象,他们的成员变量是独立的。

测试代码如下:

(1)实现Runnable:

package com.loan.entity;

import lombok.Data;

@Data
public class Test2 implements Runnable{
private int ticket=100;
@Override
public void run() {
	// TODO Auto-generated method stub
	while(true){
		if(ticket>0){
			System.out.println(Thread.currentThread().getName()+"...is saling,余票:"+ticket--);
		}
	}
}
public static void main(String[] args) {
	Test2 t=new Test2();//只能使用同一个t
	new Thread(t).start();
	new Thread(t).start();
	new Thread(t).start();
	new Thread(t).start();
}
}
运行结果:



(2)继承Thread

package com.loan.entity;

public class Test3 extends Thread{
	int ticket=100;
	public void run(){
		while(true){
			if(ticket>0){
				System.out.println(Thread.currentThread().getName()+"...is saling,余票:"+ticket--);
			}
		}
	}
	public static void main(String[] args) {
		new Test3().start();
		new Test3().start();
		new Test3().start();
		new Test3().start();
	}
}
运行结果:


很明显,这种方式是错误的!

继承Thread类也可以通过内部类发方式实现。代码如下:
package com.loan.entity;

public class Test3{
	private  int ticket=100;
	class InnerClass extends Thread{
		private Test3 t3;
		InnerClass(Test3 t){
			t3=t;
		}
		public void run(){
			while(true){
				if(ticket>0){
					ticket--;
					System.out.println(Thread.currentThread().getName()+"...is saling,余票:"+ticket);
				}
			}
		}
	}
	public static void main(String[] args) {
		Test3 test3=new Test3();
		Thread t1=test3.new InnerClass(test3);
		Thread t2=test3.new InnerClass(test3);
		Thread t3=test3.new InnerClass(test3);
		Thread t4=test3.new InnerClass(test3);
		t1.setName("t1");
		t2.setName("t2");
		t3.setName("t3");
		t4.setName("t4");
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		}
}

运行结果:


二、Thread优势

1、使用线程的方法方便一些,例如:获取线程的Id(Thread.currentThread().getId())、线程名(Thread.currentThread().getName())、线程状态(Thread.currentThread().getState())等

2、操作同一变量,但是线程调用run方法内容不同时,使用Thread内部类的方式进行,例如生产者、消费者模式

生产者消费者多线程例子:

package com.loan.entity;

public class Store {
	private final int MAX_SIZE=2;//仓库总共可存放货物
	private int count=0;//当前仓库货物
	public synchronized void add() throws InterruptedException{
		while(count>=MAX_SIZE){
			System.out.println("仓库已满");
			System.out.println(Thread.currentThread().getName()+"等待中。。。。");
			this.wait();
		}
			count++;
			System.out.println(Thread.currentThread().getName()+"存入仓库,当前货物数:"+count);
			this.notify();
	}
	public synchronized void remove() throws InterruptedException{
		while(count<=0){
			System.out.println("仓库空了");
			System.out.println(Thread.currentThread().getName()+"等待中。。。。");
			this.wait();
		}
			count--;
			System.out.println(Thread.currentThread().getName()+"取出货物,当前货物数:"+count);
			this.notify();
	}
	public static void main(String[] args) {
		Store s=new Store();
		Thread producer1=s.new Producer(s);//成员内部类需通过对象访问
		Thread producer2=s.new Producer(s);
		Thread consumer1=s.new Consumer(s);
		Thread consumer2=s.new Consumer(s);
		producer1.setName("producer1");//利用Thread中的方法
		producer2.setName("producer2");
		consumer1.setName("consumer1");
		consumer2.setName("consumer2");
		producer1.start();
		producer2.start();
		consumer1.start();
		consumer2.start();
	}
	class Producer extends Thread{
		private Store store;
		Producer(Store s){
			store=s;
		}
		public void run(){
			while(true){
				try {
					store.add();
					Thread.sleep(10000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	class Consumer extends Thread{
		private Store store;
		Consumer(Store s){
			store=s;
		}
		public void run(){
			while(true){
				try {
					store.remove();
					Thread.sleep(15000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

运行结果:

  • 3
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值