------- 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--);
}
}
}
同步于非同步方法
当一个同步代码函数的锁,被一个非同步函数访问,并修改时。
非同步函数的运行将不受同步函数的影响。
死锁
通常死锁的出现时同步中嵌套同步,而锁却不同。