参考资料
- 菜鸟教程
- 极客视频课程
线程固定的操作状态:
- 创建状态:新建一个Thread对象,准备好了一个多线程的对象,它保持这个状态直到程序 start() 这个线程;
- 就绪状态:已经实例化后调用了start()方法,等待CPU的调度,即等待JVM里线程调度器的调度;
- 运行状态:执行run()方法;
- 阻塞状态:暂时停止执行,可能将资源交给其他线程使用;
- 死亡状态(终止状态):线程销毁
线程常用方法:
新建线程对象 :
1、继承Thread 类:
public class MyThread extends Thread {
private String name;
public MyThread(String name){
this.name = name;
}
public void run(){
for (int i=0;i<10;i++){
System.out.println(name+":"+i);
}
}
public static void main(String[] args) {
Thread thread1 = new MyThread("A");
Thread thread2 = new MyThread("B");
// 启动线程
thread1.start();
thread2.start();
}
}
2、实现Runnable接口:
public class MyRunnable implements Runnable {
private String name;
public MyRunnable(String name){
this.name = name;
}
// 抽象方法
@Override
public void run() {
for(int i = 1;i<10;i++){
System.out.println(name+":"+i);
}
}
public static void main(String[] args) {
MyRunnable r1 = new MyRunnable("A");
MyRunnable r2 = new MyRunnable("B");
//传递Runnable对象给thread
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
}
启动方法依旧是调用thread的start方法。
- 取得当前线程对象 currentThread(),线程名称getName()
获取线程名称就要先获取线程,thread有一个获取当前线程的方法,如下所示:
class ThisRunnable implements Runnable{
private String name;
public ThisRunnable (String name){
this.name = name;
}
@Override
public void run() {
for (int i=0;i<10;i++){
System.out.println("当前对象:"+Thread.currentThread());
System.out.println("当前对象名称:"+Thread.currentThread().getName());
}
}
}
public class testThreadOne {
public static void main(String[] args) {
ThisRunnable r1 = new ThisRunnable("A");
Thread thread1 = new Thread(r1);
thread1.start();
}
}
- 判断线程是否启动 isAlive()
class ThisRunnable implements Runnable{
private String name;
public ThisRunnable (String name){
this.name = name;
}
@Override
public void run() {
System.out.println("当前对象:"+Thread.currentThread());
System.out.println("当前对象名称:"+Thread.currentThread().getName());
}
}
public class testThreadOne {
public static void main(String[] args) {
ThisRunnable r1 = new ThisRunnable("A");
Thread thread1 = new Thread(r1);
System.out.println(thread1.isAlive());
thread1.start();
System.out.println(thread1.isAlive());
}
}
输出结果:
false
true
当前对象:Thread[Thread-0,5,main]
当前对象名称:Thread-0
- 线程的强行运行 join()
class JoinRunnable implements Runnable{
private String name;
public JoinRunnable (String name){
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(name + ":" + i);
}
}
}
public class JoinThread {
public static void main(String[] args) {
JoinRunnable r1 = new JoinRunnable("A");
Thread thread1 = new Thread(r1);
thread1.start();
for (int i = 0;i<10;i++){
if (i>4){
try {
//抢主线程CUP,执行完线程后再还给主线程
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//运行先是主线程
System.out.println( "主线程:"+i);
}
}
}
- 线程的休眠 sleep()
每隔一秒,打印出一个线程
class JoinRunnable implements Runnable{
private String name;
public JoinRunnable (String name){
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
System.out.println(name + ":" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class JoinThread {
public static void main(String[] args) {
JoinRunnable r1 = new JoinRunnable("A");
Thread thread1 = new Thread(r1);
thread1.start();
}
}
- 线程的礼让 yeiled()
class JoinRunnable implements Runnable{
private String name;
public JoinRunnable (String name){
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(name + ":" + i);
if (i == 5) {
System.out.println("礼让");
Thread.yield();
}
}
}
}
public class JoinThread {
public static void main(String[] args) {
JoinRunnable r1 = new JoinRunnable("A");
JoinRunnable r2 = new JoinRunnable("B");
Thread thread1 = new Thread(r1);
Thread thread2 = new Thread(r2);
thread1.start();
thread2.start();
}
}
执行结果:
A:0
A:1
A:2
A:3
A:4
A:5
礼让
B:0
B:1
B:2
B:3
B:4
B:5
礼让
A:6
A:7
A:8
A:9
B:6
B:7
B:8
B:9
线程优先级:
优先级顺序:
MAX_PRIORITY ;
NORM_PRIORITY;
MIN_PRIORITY。
Java 线程的优先级是一个整数,其取值范围是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。
默认情况下,每一个线程都会分配一个优先级 NORM_PRIORITY(5)。
具有较高优先级的线程对程序更重要,并且应该在低优先级的线程之前分配处理器资源。但是,线程优先级不能保证线程执行的顺序,下面例子优先级启动比较严格。
class GradeRunnable implements Runnable {
public void run(){
for (int i=0;i<10;i++){
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class GradeThread {
public static void main(String[] args) {
Thread t1 = new Thread(new GradeRunnable(),"A");
Thread t2 = new Thread(new GradeRunnable(),"B");
Thread t3 = new Thread(new GradeRunnable(),"C");
t1.setPriority(Thread.MIN_PRIORITY);
t2.setPriority(Thread.NORM_PRIORITY);
t3.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();
t3.start();
}
}
结果显示
C
B
A
C
B
A
C
B
A
C
B
A
C
B
A
C
B
A
C
B
A
C
B
A
C
B
A
C
B
A
线程同步:
资源共享时需要使用同步:
1、同步代码块,代码块前面添加synchronized,此部分代码块就是同步代码块;
格式:
synchronized(同步对象){
}
class TogetherThread implements Runnable{
private int ticket = 5;
public void run(){
for (int i=0;i<10;i++) {
synchronized (this) {
if (ticket > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "卖出车票" + ticket--);
}
}
}
}
}
public class ThreadDemo{
public static void main(String[] args) {
TogetherThread togetherThread = new TogetherThread();
Thread thread1 = new Thread(togetherThread,"窗口1");
Thread thread2 = new Thread(togetherThread,"窗口2");
Thread thread3 = new Thread(togetherThread,"窗口3");
// 启动线程
thread1.start();
thread2.start();
thread3.start();
}
}
结果:
窗口1卖出车票5
窗口1卖出车票4
窗口3卖出车票3
窗口2卖出车票2
窗口3卖出车票1
2、同步方法:
代码块可以同步,函数方法也是可以同步的
同步方法格式:
synchronized void 方法名称(){
}
class TogetherThread implements Runnable{
private int ticket = 5;
public void run(){
for (int i=0;i<10;i++) {
tell();
}
}
synchronized void tell() {
if (ticket > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "卖出车票" + ticket--);
}
}
}
public class ThreadDemo{
public static void main(String[] args) {
TogetherThread togetherThread = new TogetherThread();
Thread thread1 = new Thread(togetherThread,"窗口1");
Thread thread2 = new Thread(togetherThread,"窗口2");
Thread thread3 = new Thread(togetherThread,"窗口3");
// 启动线程
thread1.start();
thread2.start();
thread3.start();
}
}
结果:
窗口1卖出车票5
窗口3卖出车票4
窗口3卖出车票3
窗口2卖出车票2
窗口2卖出车票1
线程死锁
多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。
线程的生命周期:
理解:
创建状态对应被创建;
就绪状态对应临时阻塞状态,意味着start()方法启动后,已经获得了cup执行资格(还在排队),但还没有获得cpu的执行权;
运行状态对应运行,表示cpu正在执行,获得cpu执行权;
阻塞状态对应冻结,表示释放执行资格,同时释放执行权;
1、可以让正在运行的进程通过sleep()方法进入此状态,睡眠时间到后,线程会重新获得cpu执行资格,进入就绪状态;
2、调用wait()方法,使此线程进入阻塞状态,但是无法自己唤醒,所以需要使用notify()方法唤醒此进程。
死亡状态对应消亡,表示线程已经结束,线程运行结束后可以进入此状态,或者直接使用stop()方法直接停止该进程。