黑马程序员_多线程的创建和运行机制学习笔记

------- android培训java培训、期待与您交流! ----------


1、线程类的定义与运行:

1)直接继承Thread类,覆盖Run方法,eg:

/**
 * 继承Thread实现线程类
 * @author CBY
 *
 */
public class DemoThread extends Thread{
	//自定义线程标识
	private int num;
	DemoThread(int num) {
		this.num = num;
	}
	public void run() {
		System.out.println("Thread " + num + " Start");
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("Thread " + num + " Do");
	}
}
验证:

/**
 * 验证操作
 * @author CBY
 *
 */
class TestMain {
	public static void main(String[] args) {
		//新建第一个线程
		DemoThread dt1 = new DemoThread(1);
		//新建第二个线程
		DemoThread dt2 = new DemoThread(2);
		//启动第一个线程
		dt1.start();
		//启动第二个线程
		dt2.start();
	}
}

2)通过实现Runnable接口,并将实现后的类,入参到new Thread的构造器中,eg:

/**
 * 实现Runnable的类
 * @author CBY
 *
 */
class DemoObject implements Runnable {
	//自定义线程标识
	private int num;
	DemoObject(int num) {
		this.num = num;
	}
	public void run() {
		System.out.println("Thread " + num + " Start");
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("Thread " + num + " Do");
	}
}
验证:

public static void main(String[] args) {
		//定义对象1
		DemoObject do1 = new DemoObject(1);
		//定义对象2
		DemoObject do2 = new DemoObject(2);
		//定义线程1,并插入对象1
		Thread trd1 = new Thread(do1);
		//定义线程2,并插入对象2
		Thread trd2 = new Thread(do2);
		//启动线程1
		trd1.start();
		//启动线程2
		trd2.start();
	}

3)如何选择以上两种方法的实现:

之前在论坛中,遇到过这个问题。把当时想法和回复贴过来。以备查找吧:

无论是实现Runnable方法,还是继承Thread类,其实都是可以的。

主要还是看对象的设计需求。

Runnable的一个例子:

比如:让设计一个动物的类继承体系,猫、狗、兔子,都继承于动物,且都有“吃”这个方法:


如果要让多只狗狗同时在“吃”,那么,多线程,显然是首选实现方式。

但JAVA的继承体系是单根的,也就是只有一个父节点。“猫”、“狗”、“兔子”都已经继承了“动物”这个父类,显然再想继承Thread是不可能的。

所以只能用Runnable接口,实现run()方法后,再交给Thread去运行。

这样的优点,就是不破坏类本身的继承体系。

也是你以后在工作中,相对于继承Thread类来说,更加优选的方案。

至于继承Thread类,如果确定这个类本身就是一个线程类,那直接继承Thread是完全可以的。


2、线程的运行状态即状态转换:(如图)



3、线程安全(synchronized):

同步函数:

对象的同步函数的锁是对象this。

类的同步函数的锁是类字节码。

eg:

//同步函数
	@Override
	public synchronized void run() {
		while(ticketNum>0)
		{
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			System.out.println(Thread.currentThread().getName() + ":" + ticketNum--);
		}
	}
同步代码块:

需要定义指定传入的同步锁。

eg:

//同步代码块
	@Override
	public void run() {
		
		synchronized(this)
		{
			while(ticketNum>0)
			{
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + ":" + ticketNum--);
			}
		}
	}

同步于非同步方法

当一个同步代码函数的锁,被一个非同步函数访问,并修改时。
非同步函数的运行将不受同步函数的影响。


死锁

通常死锁的出现时同步中嵌套同步,而锁却不同。




------- android培训java培训、期待与您交流! ----------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值