线程啊是个好东西,但是平时工作很少自己创建线程,所以一些基础的操作可能就不容易记起来,这篇文章常看看有益身心健康
public class TestDeamon {
public static void main(String[] args) {
// lambda 表达式
Thread t1 = new Thread(()->System.out.println("这是一个线程01!"));
Thread t2 = new Thread(()->{
System.out.println("这是一个线程02!");
});
// 匿名内部类
Thread t3 = new Thread(){
@Override
public void run() {
System.out.println("这是一个线程03!");
}
};
// 继承Thread
Thread t4 =new MyThread04();
// 实现Runnable 参数是Runnable
Thread t5 = new Thread(new MyRunnable());
// 时效内
// 启动线程
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
/**
* 继承Thread
* public class Thread implements Runnable
* thread是实现了Runnable接口
*/
class MyThread04 extends Thread{
@Override
public void run() {
System.out.println("这是一个线程04!");
}
}
/**
* 实现Runnable
*/
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("这是一个线程05!");
}
}
// 启动线程
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
输出:
这是一个线程01!
这是一个线程02!
这是一个线程03!
这是一个线程04!
这是一个线程05!
线程启动之后就会执行run方法
执行完for循环 自动结束
// lambda 表达式
Thread t1 = new Thread(()->{
for (int i = 0; i < 10; i++) {
try{
Thread.sleep(1000);
System.out.println("===");
} catch (Exception e) {
e.printStackTrace();
}
}
});
t1.start();
stop已经被废弃,stop太粗暴,不温柔,所以没人喜欢..
// lambda 表达式
Thread t1 = new Thread(()->{
for (;;) {
try{
Thread.sleep(1000);
System.out.println("===");
} catch (Exception e) {
e.printStackTrace();
}
}
});
t1.start();
// 10秒后 停止
Thread.sleep(10000);
// 停止
t1.stop();
很容易产生数据不一致 因为某一个事务或者一块代码没执行完的时候 就有可能被干掉
举个例子:
// lambda 表达式
Thread t1 = new Thread(()->{
System.out.println("对象去洗澡了");
try{
System.out.println("钻被窝等着...");
Thread.sleep(10000);
System.out.println("洗白白 开小会");
} catch (Exception e) {
e.printStackTrace();
}
});
t1.start();
// 10秒后 停止
Thread.sleep(5000);
// 停止
t1.stop();
结果:
对象去洗澡了
钻被窝等着...
可以看到哈,你等了半天,还没开始开小会就被打断了 。。
suspend 让线程暂停
resume 让暂停的线程继续执行
suspend容易产生死锁等问题 如果忘记resume或者resume异常 那如果suspend的线程持有锁的话,就死锁了
public class TestDeamon03 {
// 锁 表示对象
public static Object obj = new Object();
public static void main(String[] args) throws InterruptedException {
// lambda 表达式
Thread t1 = new Thread(()->{
synchronized (obj){
try {
System.out.println("我出去打工了 留对象在家");
Thread.sleep(10000);
System.out.println("我回来了 娶我对象 ");
} catch (Exception e) {
e.printStackTrace();
}
}
});
t1.start();
// 2秒后 暂停
Thread.sleep(2000);
// 暂停
t1.suspend();
Thread.sleep(2000);
// 恢复
resumeObj(t1);
}
// resume 模拟异常
static void resumeObj(Thread t){
int i = 1/0;
t.resume();
}
}
你找了个对象,把人家放家里,说打工1年回来娶,然后你回家途中找了个别人,一起幸福生活了,你对象在家...
被你占用,你又不通知、不释放
volatile(保证内存可见)修饰一个变量 时间可能控制不是很精确 因为volatile修改了之后刷新到内存 在另一个线程读取到 还是需要时间的 虽然很快 但是一般的情况 都没什么问题
public class TestDeamon04 {
static volatile boolean flag = true;
public static void main(String[] args) throws InterruptedException {
// lambda 表达式
Thread t1 = new Thread(()->{
int count =0;
// flag == true 循环 flag==false 停止循环 也就结束线程了
while (flag) {
try {
Thread.sleep(1);
count++;
} catch (Exception e){
e.printStackTrace();
}
}
System.out.println("count:"+count);
});
t1.start();
// 1秒后 停止
Thread.sleep(1000);
flag = false;
}
}
多次输出结果:
505、525、507、512
可以看到每次输出结果是不确定的 ,
这种方式只能保证到达某个条件了就停止线程
但是不能控制线程准确点停止
比如你想让一个线程循环100次就停止 很难准确控制
也算标志位 但是比volatile高级一点 比如sleep、wait等操作会被中断
// lambda 表达式
final Thread t1 = new Thread(()->{
int count =0;
//
while (!Thread.interrupted()) {
try {
count++;
} catch (Exception e){
e.printStackTrace();
}
}
System.out.println("count:"+count);
});
t1.start();
// 1秒后 停止
Thread.sleep(1000);
t1.interrupt();
中断sleep测试:interrupt会中断sleep在异常捕获里边break就行了 而标志位flag是无法做到的
public class TestDeamon06 {
static volatile boolean flag = true;
public static void main(String[] args) throws InterruptedException {
// lambda 表达式
final Thread t1 = new Thread(()->{
//
while (!Thread.interrupted()) {
try {
Thread.sleep(20000000);
} catch (Exception e){
break;
}
}
System.out.println("interrupted 结束 ");
});
// lambda 表达式
final Thread t2 = new Thread(()->{
while (flag) {
try {
Thread.sleep(20000000);
} catch (Exception e){
break;
}
}
System.out.println("volatile-结束");
});
t1.start();
t2.start();
// 1秒后 停止
Thread.sleep(1000);
t1.interrupt();
flag = false;
}
}
总结:
stop 、suspend resume 已废弃
volatile标志位 无法中断sleep wait 等操作
interrupt 相当于标志位但是可以中断sleep wait等操作 捕获InterruptedException异常 进行线程结束
可能还有其他方式 大多数是基于标志位的
欢迎关注公众号:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有