前置知识:创建线程的方式。
线程生命周期:
(图片来自狂神Java说)
线程的一些方法:
如何让线程停止:
一般建议让线程自己停下来。
如果想让线程停止下来,不推荐使用 JDK 提供的 stop()、destroy() 方法 – > 已经废弃。
可以通过设置一个标志位进行终止变量, 当 flag = false,则线程终止运行。
package thread;
public class StopThread implements Runnable {
private boolean flag = true;
@Override
public void run() {
int i = 0;
// 利用 flag 标志位停止该线程
while (flag) {
System.out.println("我还没有停止哟。。。。。。" + i++);
}
}
public void stopThread() {
flag = false;
}
public static void main(String[] args) {
// 要想使用 StopThread 中的方法,创建的对象必然是 StopThread 类型的
StopThread realRole = new StopThread();
// 新生状态
Thread t = new Thread(realRole);
// 就绪状态
t.start();
for (int i = 0; i < 1000; i++) {
System.out.println("主线程在加速跑!!!!!!!!!!!!!!!!!!!!!!" + i);
if(i == 900) {
realRole.stopThread();
System.out.println("线程终止了。。。。。。。");
}
}
}
}
效果图:
线程休眠:
sleep(时间)指定当前线程阻塞的毫秒数。
sleep 存在异常 InterruptedException。
sleep 时间达到后线程进入就绪状态。
sleep 可以模拟网络延时,倒计时等。
每个对象都有一把锁,Sleep 不会释放锁(同步线程时会释放)。
案例一:倒计时
package thread;
// 模拟倒计时: 放大问题的发生性
public class SleepThread {
public void tenDown() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SleepThread real = new SleepThread();
for (int i = 10; i >= 0; i--) {
System.out.println(i);
real.tenDown();
}
}
}
案例二: 网络延时
线程睡眠会放大问题的发生性,举例来说,火车站的票数是固定的,有三个窗口,在同一时刻可能有三个用户都在三个窗口面前买票(这就是sleep的用处),遇到这种问题该怎么处理呢?如果三个售票窗口不加入同步机制,那么就会引起线程不安全的问题(假设A、B、C三个售票窗口最后都看到还有一张票,就都会去出售,A 出售最后一张票,总票数为 0,但是在刚刚的同一时刻,B、C窗口看到的都是还有一张票,这时候 B 就会去出售,造成总票数为 -1,接着C也会去出售,因为 三个窗口同时看到还有一张票),所以sleep() 可以更加真实的显现我们的现实生活。
package thread;
// 多个线程操作同一个对象的情况下,线程不安全(大家都看到了最后一张票),数据紊乱
public class Demo04 implements Runnable{
private int ticketNum = 10;
@Override
public void run() {
while(true) {
// 多个线程有可能会在同一时刻看到同样的票
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"拿到了第" + ticketNum -- + "票" );
if(ticketNum <= 0 ) break;
}
}
public static void main(String[] args) {
Runnable ticket = new Demo04();
new Thread(ticket,"小A").start();
new Thread(ticket,"小B").start();
new Thread(ticket,"小美眉").start();
}
}
效果图:
案例三: 打印系统当前时间:
package thread;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CurrentTime {
public static void main(String[] args) throws InterruptedException {
// 获取系统当前时间
Date date = new Date(System.currentTimeMillis());
while(true) {
// 根据格式打印信息
System.out.println(new SimpleDateFormat("HH:mm:ss").format(date));
// 延迟 1 秒
Thread.sleep(1000);
// 重新获取当前时间
date = new Date(System.currentTimeMillis());
}
}
}
线程礼让: yield
礼让线程,让当前正在执行的线程暂停,但不阻塞。
让线程从运行状态转为就绪状态。
让CPU重新调度让不一定成功,看CPU心情。
package thread;
public class TestYield {
public static void main(String[] args) {
new Thread(new MyYield(),"a").start();
new Thread(new MyYield(),"b").start();
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始执行。。。。");
if(Thread.currentThread().getName().equals("a")) {
Thread.yield();
}
System.out.println(Thread.currentThread().getName() + "线程终止了。。。。。。。");
}
}
效果图:
礼让成功:
礼让不一定成功:
线程强制执行: join
join 合并线程,待此线程执行完成后,再执行其他线程,
类似于VIP插队。
package thread;
public class TestJoin implements Runnable {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("线程VIP来啦。。。。。。。。");
}
}
public static void main(String[] args) {
TestJoin realRole = new TestJoin();
Thread t = new Thread(realRole);
t.start();
for (int i = 0; i < 100; i++) {
System.out.println("main.............."+i);
if(i == 50) {
try {
// 到 50 的时候,另一个线程强制执行
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
效果图:
线程的优先级:
Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。
线程的优先级用数字表示,范围 1 ~ 10;
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
可以使用以下方式改变或获取优先级:
getPriority();
setPriority(int xxx);
案例:
package thread;
public class TestPriority {
public static void main(String[] args) {
System.out.println( "主线程:" + Thread.currentThread().getPriority());
MyPriority realRole = new MyPriority();
Thread t1 = new Thread(realRole,"t1");
Thread t2 = new Thread(realRole,"t2");
Thread t3 = new Thread(realRole,"t3");
Thread t4 = new Thread(realRole,"t4");
t1.setPriority(2);
t1.start();
t2.setPriority(6);
t2.start();
t3.setPriority(Thread.MAX_PRIORITY);
t3.start();
t4.setPriority(Thread.MIN_PRIORITY);
t4.start();
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ":" + Thread.currentThread().getPriority());
}
}
效果图: