多线程
一个进程中至少有1+个线程
创建线程的两种方式
继承Thread
步骤:
-
定义类继承Thread类;
-
目的是复写run方法,将要让线程运行的代码都存储到run方法中;
-
通过创建Thread类的子类对象,创建线程对象;
-
调用线程的start方法,开启线程,并执行run方法。
特点:
- 当类去描述事物,事物中有属性和行为。如果行为中有部分代码需要被多线程执行,同时还在操作属性。就需要该类继承Thread类,那么产生该类的对象作为线程对象,可是这样做会导致,每个对象都存储一份属性数据。无法在多个线程中共享该数据。加上静态,虽然实现了共享,但是生命周期太长。
线程状态:
被创建:start()
运行:具备执行资格,同时具备执行权;
冻结:sleep(time),wait()—notify()唤醒;线程释放了执行权,同时释放执行资格;
临时阻塞状态:线程具备cpu的执行资格,没有cpu的执行权;
消亡:stop()
实现Runnable接口
步骤:
-
定义类实现Runnable接口。
-
覆盖接口中的run方法(用于封装线程要运行的代码)。
-
通过Thread类创建线程对象;
-
将实现了Runnable接口的子类对象作为实际参数传递给Thread类中的构造函数。
为什么要传递呢?因为要让线程对象明确要运行的run方法所属的对象。
5,调用Thread对象的start方法。开启线程,并运行Runnable接口子类中的run方法。
特点:
- 描述失误的类中封装了属性和行为,如果有部分代码被多线程所执行。同时还在操作属性,那么可以通过实现Runnable接口
的方式。
因为该方式是定义一个Runnable接口的子类独显,可以被多个相处所操作实现了数据的共享。 - 实现Runnable的接口的好处,避免了单继承的局限性。
如果一个类明确了自己的父类,那么很遗憾,他就不可以继承Thread。因为java不支持多继承。
join
该方法也是一种阻塞,指在当前运行的A线程中加入一个新的线程B,A线程此时属于阻塞状态,要等待B线程全部运行完毕后,才能继续运行A线程。
Join方法要加在当前运行线程的代码块中,例如:
public class MyRunnable implements Runnable{
public void run() {
MyRunnable2 myRunnable2 = new MyRunnable2();
Thread thread = new Thread(myRunnable2, "线程2");
thread.start();
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class MyRunnable2 implements Runnable{
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
重入锁(对象互斥锁)
未完
Q.E.D.