Java多线程-线程方法
线程方法
方法 | 说明 |
---|---|
setPriority(int newPriority) | 更改线程的优先级 |
static void sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程体休眠 |
void join() | 等待该线程终止(插队) |
static void yield() | 暂停当前正在执行的线程对象,并执行其他线程 |
void interrupt() | 中断线程,别用这个方式 |
boolean isAlive() | 测试线程是否处于活动状态 |
如何停止线程
不推荐使用JDK提供的stop(),destroy()方法
推荐线程自己停下来
建议使用一个标志位进行终止变量,当flag = false,则终止线程运行
//测试线程停止
//1.建议线程自己停止---->利用次数,不建议死循环
//2.建议使用标志位---->设置一个标志位
//3.不要使用stop,destroy等过时或者jdk不建议使用的方法
public class TestStop implements Runnable{
//设置一个标志位
private boolean flag = true;
@Override
public void run() {
int i = 0;
while (flag){
System.out.println("run...Thread"+i++);
}
}
//设置一个公开的方法,变更标志位,停止线程
public void stop(){
this.flag = false;
}
public static void main(String[] args) {
TestStop ts = new TestStop();
new Thread(ts).start();
for (int i =0;i<1000;i++){
System.out.println("main"+i);
if(i==900){
//调用stop方法,切换标志位,停止线程
ts.stop();
System.out.println("线程停止了");
}
}
}
}
线程休眠
- sleep(时间)指定当前线程阻塞的毫秒数
- sleep存在异常InterruptedException
- sleep事件达到后线程进入就绪状态
- sleep可以模拟网络延时,倒计时等
- 每一个对象都有一个锁,sleep不会释放锁
//模拟网络延时:放大问题的发生性
public class TestSleep implements Runnable{
private int ticketNums = 10;
@Override
public void run() {
while (true){
if (ticketNums<=0){
break;
}
//模拟延时
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"拿到了倒数第"+ticketNums--+"张票");//获取当前线程名
}
}
public static void main(String[] args) {
TestSleep t = new TestSleep();
new Thread(t,"小明").start();
new Thread(t,"小兰").start();
new Thread(t,"小王").start();
}
}
import java.text.SimpleDateFormat;
import java.util.Date;
//模拟倒计时
public class TestSleep2 {
public static void main(String[] args) {
tenDown();
//打印当前时间
Date startTime = new Date(System.currentTimeMillis());
while (true){
try {
Thread.sleep(1000);
System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
startTime = new Date(System.currentTimeMillis());//更新当前系统时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//模拟倒计时
public static void tenDown(){
int num =10;
while (true){
try {
Thread.sleep(1000);
System.out.println(num--);
if (num<=0){
break;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程礼让
礼让线程,让当前正在执行的线程暂停,但不阻塞
将线程从运行状态转为就绪状态
让cpu重新调度,礼让不一定成功!,看CPU如何调度
//测试礼让线程
//礼让不一定成功,看CPU如何调度
public class TestYield {
public static void main(String[] args) {
MyYield myYield = new MyYield();
new Thread(myYield,"A").start();
new Thread(myYield,"B").start();
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始执行");
Thread.yield();//线程礼让
System.out.println(Thread.currentThread().getName()+"线程停止执行");
}
}
结果1 结果2
A线程开始执行 A线程开始执行
B线程开始执行 A线程停止执行
A线程停止执行 B线程开始执行
B线程停止执行 B线程停止执行
线程强制执行
Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞
可以想象成插队
//测试join方法,想象为插队
public class TestJoin implements Runnable{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("线程VIP来了"+i);
}
}
public static void main(String[] args) throws InterruptedException {
//
TestJoin testJoin = new TestJoin();
Thread thread = new Thread(testJoin);
thread.start();
//主线程
for (int i = 0; i < 1000; i++) {
if (i==200){//200以前是并行
thread.join();//插队
}
System.out.println("main"+i);
}
}
}
线程状态
Thead.State
- new
尚未启动的线程处于此状态。 - RUNNABLE
在Java虚拟机中执行的线程处于此状态。 - BLOCKED
被阻塞等待监视器锁定的线程处于此状态。 - WAITING
正在等待另一个线程执行特定动作的线程处于此状态。 - TIMED_WAITING
正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。 - TERMINATED
已退出的线程处于此状态。
//观察测试线程状态
public class TestState {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("......");
});
//观察状态
Thread.State state = thread.getState();
System.out.println(state);//NEW
//观察启动后
thread.start();
state = thread.getState();
System.out.println(state);//RUN
while(state!=Thread.State.TERMINATED){//只要线程不终止,就一致输出状态
Thread.sleep(100);
state = thread.getState();
System.out.println(state);
}
thread.start();//报错,死亡后的线程不能再start
}
}
NEW
RUNNABLE
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
...
......
TERMINATED
线程优先级
- Java提供了一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定线程的执行顺序
- 线程的优先级用数字表示[1,10],数字越大,优先级越高
- Thread.MIN_PRIORITY = 1;
- Thread.MAX_PRIORITY = 10;
- Thread.NORM_PRIORITY = 5;
- 通过以下方式改变或获取优先级
- getPriority().setPriority(int xxx)
//测试线程的优先级
//默认优先级:5
//设置优先级后,并不是说高的一定先执行,只是有比较大的概率先执行(主要看CPU如何调度)
//如果某段代码比较重要,可以考虑设置高的优先级
public class TestPriority {
public static void main(String[] args) {
//主线程的优先级
System.out.println(Thread.currentThread().getName()+"的优先级-->"+Thread.currentThread().getPriority());
MyPriority myPriority = new MyPriority();
Thread t1 = new Thread(myPriority);
Thread t2 = new Thread(myPriority);
Thread t3 = new Thread(myPriority);
Thread t4 = new Thread(myPriority);
Thread t5 = new Thread(myPriority);
Thread t6 = new Thread(myPriority);
//设置优先级
t1.start();
t2.setPriority(1);
t2.start();
t3.setPriority(4);
t3.start();
t4.setPriority(Thread.MAX_PRIORITY);
t4.start();
// 报错1-10
// t5.setPriority(-1);
// t5.start();
//
// t6.setPriority(11);
// t6.start();
}
}
//创建线程类
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"的优先级-->"+Thread.currentThread().getPriority());
}
}
守护(daemon)线程
- 线程分为用户线程和守护线程
- 虚拟机必须确保用户线程执行完毕
- 虚拟机不用等待守护线程执行完毕
- 如后台记录操作日志,监控内存,垃圾回收(gc)等待
//测试守护线程
//God bless you
public class TestDaemon {
public static void main(String[] args) {
God god = new God();
You you = new You();
Thread thread = new Thread(god);
thread.setDaemon(true);//默认是false 用户线程
thread.start();
//用户线程
new Thread(you).start();
/*
29999 days has gone!
====finally,good bye!====//用户线程终止
God bless you! //守护线程仍在继续,虚拟机关闭需要时间
*/
}
}
//God forever
class God implements Runnable{
@Override
public void run() {
while(true) {
System.out.println("God bless you!");
}
}
}
//You
class You implements Runnable{
@Override
public void run() {
for (int i = 0; i < 30000; i++) {
System.out.println(i+" days has gone!");
}
System.out.println("====finally,good bye!====");
}
}