大纲
一、线程理解
二、Thread类和Runnable接口的实现区别
三、线程生命周期
四、线程操作中常用方法
线程理解
在理解线程之前需要知道进程,什么是进程,什么又是线程。从日常的电脑操作中,打开一个QQ就表示一个进程,而在QQ中打开聊天窗口,就表示一个线程,一个进程中可以有多个线程。
Java中线程实现方式有两种:
1、继承Thread类
2、实现Runnable接口
范例:继承Thread类,继承此类之后需要覆写父类中的run()方法实现线程,启动线程需要调用start()方法启动线程。
package cn.txp.thread.demo; public class ThreadDemo01 extends Thread{ @Override public void run() { for(int x = 0 ; x < 5; x ++) { System.out.println(Thread.currentThread().getName() + "x=" + x); } } public static void main(String[] args) { ThreadDemo01 thread01 = new ThreadDemo01(); ThreadDemo01 thread02 = new ThreadDemo01(); thread01.start(); thread02.start(); } }
范例:实现Runnable接口,实现Runnable接口,在启动线程的时候依然实例化Thread类,调用start方法进行启动。因为线程的执行方法体是run()方法,而run是定义的Runnable接口中,Thread类是Runnable接口的实现类,提供了线程相关的操作方法,如设置线程名称,获取优先级,暂停线程,休眠线程,启动线程等操作。所以继承Runnable接口实现的线程,在启动时,需要实例化Thread类,传递一个线程进去进行启动。
package cn.txp.thread.demo; public class ThreadDemo02 implements Runnable{ private String name; public ThreadDemo02(String name) { this.name = name; } @Override public void run() { for(int x = 0 ; x < 5 ; x ++) { System.out.println(this.name + x); } } public static void main(String[] args) { ThreadDemo02 thread01 = new ThreadDemo02("线程A"); ThreadDemo02 thread02 = new ThreadDemo02("线程B"); new Thread(thread01).start(); new Thread(thread02).start(); } }
Thread类和Runnable实现的区别
Java中类是单继承的,而接口可以实现多个接口,所以使用Runnable接口可以避免单继承的实现,而这两种实现方式除了这一点之外,最重要的是多个线程资源的共享。
范例:多个线程共享
此时是通过继承Thread类实现的线程,并且实例化了三个线程,但是这三个线程无法共享,这里把三个线程都单独运行,各自去都买五张票,理因是这三个线程去共享五张票。而不是每一个都是单独的五张
package cn.txp.thread.demo; public class ThreadDemo03 extends Thread{ private String name; private int ticket; public ThreadDemo03(String name, int ticket) { this.name = name; this.ticket = ticket; } @Override public void run() { for(int i = 0 ; i < 100; i ++) { if(ticket > 0) { System.out.println("线程" + name + this.ticket --); } } } public static void main(String[] args) { ThreadDemo03 thread1 = new ThreadDemo03("线程A", 5); ThreadDemo03 thread2 = new ThreadDemo03("线程B", 5); ThreadDemo03 thread3 = new ThreadDemo03("线程C", 5); thread1.start(); thread2.start(); thread3.start(); } }
// 输出结果
线程线程A5
线程线程A4
线程线程A3
线程线程A2
线程线程A1
线程线程B5
线程线程B4
线程线程B3
线程线程B2
线程线程B1
线程线程C5
线程线程C4
线程线程C3
线程线程C2
线程线程C1
范例:通过实现Runnable接口实现资源共享,,输出接口可以发现,此时也是实例化了三个线程,但是这三个线程是去共享这5张票,而不是每一个都是单独的5张。
package cn.txp.thread.demo; public class ThreadDemo04 implements Runnable{ private String name; private int ticket; // 票 public ThreadDemo04(String name, int ticket) { this.name = name; this.ticket = ticket; } @Override public void run() { for(int i = 0 ; i < 100; i ++) { if(ticket > 0) { System.out.println("线程" + name + this.ticket --); } } } public static void main(String[] args) { ThreadDemo04 thread = new ThreadDemo04("线程", 5); new Thread(thread).start(); new Thread(thread).start(); new Thread(thread).start(); } }
// 输出结果
线程线程4
线程线程5
线程线程3
线程线程1
线程线程2
线程生命周期
线程的生命周期一共有五种状态
1、创建状态:通过new Thread() 创建一个线程就为创建状态
2、就绪状态:调用start()方法启动线程时,此时还没有运行线程,为就绪状态
3、运行状态:当线程执行run()方法过程中,就为运行状态
4、堵塞状态:嗲用了sleep(),suspend()、wait()方法暂停线程运行为堵塞状态
5、死忙状态:当run()方法执行完毕,或者调用了stop()方法停止线程,此时线程已经执行完毕,就终止线程
线程操作中常用方法
方法名称 | 描述 |
public static Thread currentThread() | 获取当前正在执行的线程 |
public final String getName() | 获取线程名称 |
public final int getPriority() | 获取线程的优先级 |
public boolean isInterrupted() | 判断当前线程是否终端,是:true 否:false |
public final boolean isAlive() | 判断线程是否被中断,是:true 否:false |
public final void join() throws Interrupted Exception | 等待线程死忙 |
public final synchronized void join(long milis) throws Interrupted Exception | 等待 milis 毫秒后,线程死忙 |
public void run() | 执行线程 |
public final void setName(String name) | 设置线程名称 |
public final void setPriority(int newPriority) | 设置线程的优先级 |
public static void sleep(long milis) throws InterruptedException | 线程休眠 milis 后在执行 |
public void start() | 启动线程 |
public static void yield() | 将当前正在执行的线程暂停,允许其他的线程执行 |
public final void setDaemon(boolean on) | 设置线程为后台运行 |
知乎文章: https://www.zhihu.com/people/tan-xu-peng-44
编程专业知识:https://www.cnblogs.com/tjava
编程开发技术问题解决CSDN:https://blog.csdn.net/qq_37291829
原文:https://www.cnblogs.com/tjava/p/13669452.html