0
点赞
收藏
分享

微信扫一扫

创建线程的方式:继承Thread和实现Runnable接口

雨鸣静声 2022-03-30 阅读 194
javaeclipse

继承Thread和实现Ruunable接口的区别

1.首先继承Thread是父类与子类的关系,实现Ruunable接口是实现类和接口的关系。

2.继承只能单继承,而接口可以多实现。(先继承后实现。)

3.如果一个类继承Thread,则不适合资源共享(成员变量加上static修饰也可以实现资源共享),但是实现了Runnable接口的话,则容易实现资源共享。

4.实现Runnable接口,增加程序的健壮性。代码可以被多个线程共享,代码和属性共享

继承Thread和实现Ruunable接口的特点

1. 继续Thread类。重写run方法。测试类时,创建多个线程,加上static修饰成员变量表示数据共享就是共同完成一个任务()。

2.实现Runnable接口,重写run方法,并且将Runnable子类对象作为参数,传入Thread对象
创建一个实现类对象实现runnable接口,测试类时,只用创建一个实现类对象,可以创建多个线程共同完成任务,(不用static修饰成员变量)

继承Thread类

// 继承Thread类
public class BeanThread extends Thread {
	// 1.声明一个成员变量用被每一个线程对象共享static修饰,
	private static int bean = 100;
	/**
	 * 2. 同步方法(重点掌握)
			用synchronized关键字修饰方法即可,在修饰符位置,返回值前面
			如果方法是static修饰的:同步的是 :当前类.class 
			如果方法是非static修饰的:同步的是: this 
			
			如果继承Thread的方式,同步方法的话,就需要将方法改为static修饰,所以说,一般我们不用同步方法
			一般建议继承Thread用同步代码块或者锁机制
	 */
	// 声明一个robBean方法表示抢豆子功能
	private static synchronized void robBean() {// 同步方法,如果方法是类方法,则同步对象默认是:当前类.class
	//private  synchronized void robBean() {//同步方法,如果方法是实例方法,则同步对象默认是:this
		Thread ct = Thread.currentThread();// 获取当前线程对象
		String name2 = ct.getName();// 获取当前线程对象名	
			if (bean > 0) {
				System.out.println(name2+":抢到豆子:" + bean);
				bean--;
			}
	}
	/**
	 * 构造方法
	 * 无参构造方法和带参构造方法 
	 */
	public BeanThread() {
		super();
	}

	public BeanThread(String name) {
		super(name);
	}
	
	/**
	 * 重写run方法,方法中用while循环调用robBean方法
	 */
	@Override
	public void run() {
			while (bean > 0) {
				// 调用抢豆子方法robBean
				robBean();
		}
	}
}

 线程测试类

/**
 * 线程测试类
 * 测试抢豆子线程BeanThread
 * 测试方式:
 *	创建5个BeanThread对象,传入线程名
 *	调用start方法启动线程
 */
public class BeanThreadTest {
	public static void main(String[] args) {
		/** 创建5个线程BeanThread对象表示窗口 */
		BeanThread t1 = new BeanThread("豆子1");
		BeanThread t2 = new BeanThread("豆子2");
		BeanThread t3 = new BeanThread("豆子3");
		BeanThread t4 = new BeanThread("豆子4");
		BeanThread t5 = new BeanThread("豆子5");
		
		//调用start方法启动线程
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
	}
}

实现Runnable接口

/**
 * 创建启动线程的方法二:Runnable方法
 */
public class BeanImpl implements Runnable{
	/**
	 * 声明一个static修饰的成员变量被每个线程共享
	 */
	// private static int bean = 100;
	private static int bean = 100; 
	// 成员变量
	 String name;	
	/**
	 * 构造方法
	 * 定义一个带参构造方法
	 */
	public BeanImpl(String name) {
		this.name = name;
	}	
	public BeanImpl() {
		// TODO Auto-generated constructor stub
	}
	/**
	 * 定义一个方法实现卖票功能
	 */
	private static synchronized void sellbean() {
			/*//获取当前线程对象,谁调用就是谁的线程
			Thread currentThread = Thread.currentThread();
			//获取线程对象的名字
			String name = currentThread.getName();*/
				/**
				 * 不加if判断,线程1买最后一张票,线程2和线程3也进来了,
				 * 在外面等待,但是他们不知道线程1卖的最后一张,就会去执行买票功能
				 * 再加一个if判断,从而线程2,3进来过后发现票没了就不会进行卖票了
				 */
				if (bean>0) {
					System.out.println(Thread.currentThread().getName()+"豆子;"+bean);
					bean--; // 每执行一次票数就减1
				}	
		}
	
/*	*//**
	 * 重写run方法,当启动线程时,默认会执行run方法
	 *
	 *//*
*/	@Override
	public void run() {
		//需要再加一个条件if票大于0
			//注意同步代码快不能加在这里,不然加在这里过后一个线程会一直执行
			while (bean>0) { //当票大于0就一直卖
				sellbean();
			}	
	}
}

实现Runnable接口测试类

/**
 * 线程测试类
 * 测试线程BeanImpl
 * 测试方式:
 *	创建1个BeanImpl对象,传入线程名
 *	调用start方法启动线程
 */
public class BeanImplTest {
	public static void main(String[] args) {
		/** 创建1个线程BeanImpl对象 */
		BeanImpl t1 = new BeanImpl();
		/**
		 * 因为Runnable接口没有start方法
		 * 需要创建线程对象将参数Runnable实现类对象传进去
		 */
		Thread t11 = new Thread(t1,"豆12");
		Thread t22 = new Thread(t1,"豆23");
		Thread t33 = new Thread(t1,"豆23");
		Thread t44 = new Thread(t1,"豆45");
		Thread t55 = new Thread(t1,"豆56");
			
		//调用start方法启动线程
		t11.start();
		t22.start();
		t33.start();
		t44.start();
		t55.start();
	}
}
举报

相关推荐

0 条评论