一:继承Thread类
Thread类是在java.lang包下面的,继承Thread类必须重写run()方法:
package org.sang.thread;
/**
* @Author: chuxia0811
* @Date: 2021/2/10 20:08
* @Description :
*/
public class MyThread extends Thread{
private String name;
public MyThread(String name){
this.name = name;
}
@Override
public void run() {
for (int i = 0;i<10;i++){
System.out.println("线程名:"+name+":"+i);
}
}
}
package org.sang.thread;
/**
* @Author: chuxia0811
* @Date: 2021/2/10 20:08
* @Description :
*/
public class ThreadDemo {
public static void main(String[] args) {
MyThread t1 = new MyThread("A");
MyThread t2 = new MyThread("B");
t1.start();
t2.start();
}
}
运行结果如下:
线程名:A:0
线程名:A:1
线程名:A:2
线程名:A:3
线程名:B:0
线程名:B:1
线程名:B:2
线程名:B:3
线程名:B:4
线程名:B:5
线程名:B:6
线程名:B:7
线程名:B:8
线程名:B:9
线程名:A:4
线程名:A:5
线程名:A:6
线程名:A:7
线程名:A:8
线程名:A:9
二:实现runable接口
package org.sang.thread;
/**
* @Author: chuxia0811
* @Date: 2021/2/10 20:25
* @Description :
*/
public class MyRunable implements Runnable {
private String name;
public MyRunable(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("线程名:" + name + ":" + i);
}
}
}
package org.sang.thread;
/**
* @Author: chuxia0811
* @Date: 2021/2/10 20:08
* @Description :
*/
public class ThreadDemo {
public static void main(String[] args) {
// MyThread t1 = new MyThread("A");
// MyThread t2 = new MyThread("B");
// t1.start();
// t2.start();
MyRunable r1 = new MyRunable("A");
MyRunable r2 = new MyRunable("B");
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
}
运行结果如下:
线程名:A:0
线程名:B:0
线程名:B:1
线程名:B:2
线程名:B:3
线程名:B:4
线程名:B:5
线程名:B:6
线程名:A:1
线程名:B:7
线程名:B:8
线程名:B:9
线程名:A:2
线程名:A:3
线程名:A:4
线程名:A:5
线程名:A:6
线程名:A:7
线程名:A:8
线程名:A:9
提示:
不管是继承于Thread类还是实现runable接口,都要创建Thread实例,调用start()方法启动多线程。
三:线程的状态
1、创建状态:准备好一个多线程的对象
2、就绪状态:调用start()方法,等待CPU调度
3、运行状态:执行run()方法
4、阻塞状态:暂时停止执行,可能将资源交给其他线程使用
5、终止状态(死亡状态):线程销毁
四:线程的常用方法
1、取得线程名称:getName()
2、取得当前线程对象:currentThread()
3、判断线程是否启动:isAlive()
4、线程的优先执行:join()
5、线程的礼让:yied()
6、线程的休眠:sleep()
五:线程的优先级
1_MIN_PRIORITY
10_MAX_PRIORITY
5_NORM_PRIORITY
如果什么都不设置默认是5
示例代码如下:
package org.sang.thread;
/**
* @Author: chuxia0811
* @Date: 2021/2/10 20:48
* @Description :
*/
public class Thread_priority {
public static void main(String[] args) {
Thread t1 = new Thread(new ThRun(),"A");
Thread t2 = new Thread(new ThRun(),"B");
Thread t3 = new Thread(new ThRun(),"C");
t1.setPriority(Thread.MIN_PRIORITY);
t2.setPriority(Thread.NORM_PRIORITY);
t3.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();
t3.start();
}
}
class ThRun implements Runnable{
@Override
public void run() {
for (int i = 1;i<=5;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
运行结果如下:
C:1
C:2
C:3
C:4
C:5
B:1
B:2
B:3
B:4
B:5
A:1
A:2
A:3
A:4
A:5
可以发现:优先级高的线程抢占CPU的资源越快,所以C最先执行,B次之,C最后执行。
六:线程同步
首先来一个经典的案例:车站剩下5张票,3个窗口同时售卖:
package org.sang.thread;
/**
* @Author: chuxia0811
* @Date: 2021/2/10 21:00
* @Description :
*/
public class ThreadTickets {
public static void main(String[] args) {
Tickets m = new Tickets();
Thread t1 = new Thread(m);
Thread t2 = new Thread(m);
Thread t3 = new Thread(m);
t1.start();
t2.start();
t3.start();
}
}
class Tickets implements Runnable {
private static int ticket = 5;
//假设当前有5张票,3个窗口在卖
@Override
public void run() {
for (int i = 0; i < 10; i++) {
if (ticket > 0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("车票:" + ticket--);
}
}
}
}
运行结果出现下面这种情况:
车票:5
车票:4
车票:3
车票:2
车票:1
车票:0
车票:-1
总共5张票,卖出去了7张,出现负数的情况,这就是在多线程并发的过程中没有线程同步导致的。
下面优化下:
1)同步代码块
package org.sang.thread;
/**
* @Author: chuxia0811
* @Date: 2021/2/10 21:00
* @Description :
*/
public class ThreadTickets {
public static void main(String[] args) {
Tickets m = new Tickets();
Thread t1 = new Thread(m);
Thread t2 = new Thread(m);
Thread t3 = new Thread(m);
t1.start();
t2.start();
t3.start();
}
}
class Tickets implements Runnable {
private static int ticket = 5;
//假设当前有5张票,3个窗口在卖
@Override
public void run() {
for (int i = 0; i < 10; i++) {
//将我们要执行的代码放在synchronized同步代码块里
synchronized (this) {
if (ticket > 0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("车票:" + ticket--);
}
}
}
}
}
运行结果如下:
车票:5
车票:4
车票:3
车票:2
车票:1
运行速度慢了很多,但资源共享了,更安全了。
2)同步方法
package org.sang.thread;
/**
* @Author: chuxia0811
* @Date: 2021/2/10 21:00
* @Description :
*/
public class ThreadTickets {
public static void main(String[] args) {
Tickets m = new Tickets();
Thread t1 = new Thread(m);
Thread t2 = new Thread(m);
Thread t3 = new Thread(m);
t1.start();
t2.start();
t3.start();
}
}
class Tickets implements Runnable {
private static int ticket = 5;
//假设当前有5张票,3个窗口在卖
@Override
public void run() {
for (int i = 0; i < 10; i++) {
//将我们要执行的代码放在synchronized同步代码块里
sell();
}
}
public synchronized void sell() {
if (ticket > 0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("车票:" + ticket--);
}
}
}
七:线程的生命周期