Java中一个线程执行死循环有什么后果有两个线程在并发运行java线程循环执行代码,一个线程执行的代码中含有一个死循环如:while(true)....当该线程在执行while(true)中代码时java线程循环执行代码,另一个线程会有执行 。
一.示例代码:
二.两个线程类的实现如下:
三.线程A执行methodA()java线程循环执行代码,methodA()中有一个死循环:
四.测试类:
由于线程A和线程B获得的对象锁不是同一把锁,从结果中可以看出,线程B是可以执行完成的 。而线程A由于进入了while死循环,故线程A一直执行运行下去了(整个程序未结束),但线程B会结束 。
也就是说,尽管线程A一直在while中执行,需要占用CPU 。但是,线程的调度是由JVM或者说是操作系统来负责的,并不是说线程A一直在while循环 , 然后线程B就占用不到CPU了 。对于线程A而言,相当于一个“计算密集型”作业了 。如果while循环是不断地测试某个条件是否成立 , 那么这种方式就很浪费CPU,可参考一个具体的实例:JAVA多线程之线程间的通信方式 中的“线程间的通信方式”第二点while轮询 。
如果把Service.java修改成如下:
总结:若线程A先获得对象锁时,由于while循环,线程A一直在while空循环中 。而线程B也因为无法获得锁而执行不了methodB() 。
可以看出,如果在一个线程在synchronized方法中无法退出,无法将锁释放,另一个线程就只能无限等待了 。
在Java 中多线程的实现方法有哪些,如何使用Java多线程的创建及启动
Java中线程的创建常见有如三种基本形式
1.继承Thread类 , 重写该类的run()方法 。
复制代码
1 class MyThread extends Thread {
2
3private int i = 0;
4
5@Override
6public void run() {
7for (i = 0; i100; i) {
8System.out.println(Thread.currentThread().getName()" "i);
9}
10}
11 }
复制代码
复制代码
1 public class ThreadTest {
2
3public static void main(String[] args) {
4for (int i = 0; i100; i) {
5System.out.println(Thread.currentThread().getName()" "i);
6if (i == 30) {
7Thread myThread1 = new MyThread();// 创建一个新的线程myThread1此线程进入新建状态
8Thread myThread2 = new MyThread();// 创建一个新的线程 myThread2 此线程进入新建状态
9myThread1.start();// 调用start()方法使得线程进入就绪状态
10myThread2.start();// 调用start()方法使得线程进入就绪状态
11}
12}
13}
14 }
复制代码
如上所示,继承Thread类,通过重写run()方法定义了一个新的线程类MyThread,其中run()方法的方法体代表了线程需要完成的任务,称之为线程执行体 。当创建此线程类对象时一个新的线程得以创建,并进入到线程新建状态 。通过调用线程对象引用的start()方法,使得该线程进入到就绪状态 , 此时此线程并不一定会马上得以执行,这取决于CPU调度时机 。
2.实现Runnable接口 , 并重写该接口的run()方法 , 该run()方法同样是线程执行体,创建Runnable实现类的实例,并以此实例作为Thread类的target来创建Thread对象,该Thread对象才是真正的线程对象 。
复制代码
1 class MyRunnable implements Runnable {
2private int i = 0;
3
4@Override
5public void run() {
6for (i = 0; i100; i) {
7System.out.println(Thread.currentThread().getName()" "i);
8}
9}
10 }
复制代码
复制代码
1 public class ThreadTest {
2
3public static void main(String[] args) {
4for (int i = 0; i100; i) {
5System.out.println(Thread.currentThread().getName()" "i);
6if (i == 30) {
7Runnable myRunnable = new MyRunnable(); // 创建一个Runnable实现类的对象
8Thread thread1 = new Thread(myRunnable); // 将myRunnable作为Thread target创建新的线程
9Thread thread2 = new Thread(myRunnable);
10thread1.start(); // 调用start()方法使得线程进入就绪状态
11thread2.start();
12}
13}
14}
15 }
复制代码
相信以上两种创建新线程的方式大家都很熟悉了,那么Thread和Runnable之间到底是什么关系呢?我们首先来看一下下面这个例子 。
复制代码
1 public class ThreadTest {
2
3public static void main(String[] args) {
4for (int i = 0; i100; i) {
5System.out.println(Thread.currentThread().getName()" "i);
6if (i == 30) {
7Runnable myRunnable = new MyRunnable();
8Thread thread = new MyThread(myRunnable);
9thread.start();
10}
11}
12}
13 }
14
15 class MyRunnable implements Runnable {
16private int i = 0;
17
18@Override
19public void run() {
20System.out.println("in MyRunnable run");
21for (i = 0; i100; i) {
22System.out.println(Thread.currentThread().getName()" "i);
23}
24}
25 }
26
27 class MyThread extends Thread {
28
29private int i = 0;
30
31public MyThread(Runnable runnable){
32super(runnable);
33}
34
35@Override
36public void run() {
37System.out.println("in MyThread run");
38for (i = 0; i100; i) {
39System.out.println(Thread.currentThread().getName()" "i);
40}
41}
42 }
复制代码
同样的,与实现Runnable接口创建线程方式相似,不同的地方在于
1 Thread thread = new MyThread(myRunnable);
那么这种方式可以顺利创建出一个新的线程么?答案是肯定的 。至于此时的线程执行体到底是MyRunnable接口中的run()方法还是MyThread类中的run()方法呢?通过输出我们知道线程执行体是MyThread类中的run()方法 。其实原因很简单,因为Thread类本身也是实现了Runnable接口,而run()方法最先是在Runnable接口中定义的方法 。
1 public interface Runnable {
2
3public abstract void run();
4
5 }
我们看一下Thread类中对Runnable接口中run()方法的实现:
复制代码
@Override
public void run() {
if (target != null) {
target.run();
}
}
复制代码
也就是说,当执行到Thread类中的run()方法时,会首先判断target是否存在 , 存在则执行target中的run()方法,也就是实现了Runnable接口并重写了run()方法的类中的run()方法 。但是上述给到的列子中,由于多态的存在 , 根本就没有执行到Thread类中的run()方法,而是直接先执行了运行时类型即MyThread类中的run()方法 。
3.使用Callable和Future接口创建线程 。具体是创建Callable接口的实现类 , 并实现clall()方法 。并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象作为Thread对象的target来创建线程 。
看着好像有点复杂 , 直接来看一个例子就清晰了 。
复制代码
1 public class ThreadTest {
2
3public static void main(String[] args) {
4
5CallableInteger myCallable = new MyCallable();// 创建MyCallable对象
6FutureTaskInteger ft = new FutureTaskInteger(myCallable); //使用FutureTask来包装MyCallable对象
7
8for (int i = 0; i100; i) {
9System.out.println(Thread.currentThread().getName()" "i);
10if (i == 30) {
11Thread thread = new Thread(ft);//FutureTask对象作为Thread对象的target创建新的线程
12thread.start();//线程进入到就绪状态
13}
14}
15
16System.out.println("主线程for循环执行完毕..");
17
18try {
19int sum = ft.get();//取得新创建的新线程中的call()方法返回的结果
20System.out.println("sum = "sum);
21} catch (InterruptedException e) {
22e.printStackTrace();
23} catch (ExecutionException e) {
24e.printStackTrace();
25}
26
27}
28 }
29
30
31 class MyCallable implements CallableInteger {
32private int i = 0;
33
34// 与run()方法不同的是,call()方法具有返回值
35@Override
36public Integer call() {
37int sum = 0;
38for (; i100; i) {
39System.out.println(Thread.currentThread().getName()" "i);
40sum= i;
41}
42return sum;
43}
44
45 }
复制代码
首先 , 我们发现,在实现Callable接口中,此时不再是run()方法了,而是call()方法,此call()方法作为线程执行体 , 同时还具有返回值!在创建新的线程时,是通过FutureTask来包装MyCallable对象,同时作为了Thread对象的target 。那么看下FutureTask类的定义:
1 public class FutureTaskV implements RunnableFutureV {
2
3//....
4
5 }
1 public interface RunnableFutureV extends Runnable, FutureV {
2
3void run();
4
5 }
于是,我们发现FutureTask类实际上是同时实现了Runnable和Future接口,由此才使得其具有Future和Runnable双重特性 。通过Runnable特性,可以作为Thread对象的target , 而Future特性 , 使得其可以取得新创建线程中的call()方法的返回值 。
执行下此程序,我们发现sum = 4950永远都是最后输出的 。而“主线程for循环执行完毕..”则很可能是在子线程循环中间输出 。由CPU的线程调度机制 , 我们知道,“主线程for循环执行完毕..”的输出时机是没有任何问题的,那么为什么sum =4950会永远最后输出呢?
原因在于通过ft.get()方法获取子线程call()方法的返回值时,当子线程此方法还未执行完毕,ft.get()方法会一直阻塞,直到call()方法执行完毕才能取到返回值 。
上述主要讲解了三种常见的线程创建方式,对于线程的启动而言,都是调用线程对象的start()方法,需要特别注意的是:不能对同一线程对象两次调用start()方法 。
你好,本题已解答,如果满意
请点右下角“采纳答案” 。
java中一个线程如何执行多次在线程里使用循环,然后睡眠一段时间再执行 。或者使用 java.util.Timer; java.util.TimerTask; 来设置定时执行任务 。
仅供参考
package com.kidd.test.zhidao;
/**
* Hello world!
*
*/
public class Main {
public static void main(String[] args) {
Seed seed = new Seed();
TestRunnable testRunnable = new TestRunnable(seed);
Thread thread = new Thread(testRunnable);
thread.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
seed.setEnd(true);
}
}
class TestRunnable implements Runnable {
private Seed seed;
public TestRunnable(Seed seed) {
super();
this.seed = seed;
}
public Seed getSeed() {
return seed;
}
@Override
public void run() {
while (!seed.isEnd()) {
System.out.println("线程正在执行");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Seed {
private boolean end;
public boolean isEnd() {
return end;
}
public void setEnd(boolean end) {
this.end = end;
}
}
java定义一个线程类,循环执行100次输出语句,每次输出线程名和循环的次数思路: 创建线程继承线程类或者实现线程接口
重写RUN方法 在RUN方法里面写FOR循环, 循环语句块中打印线程类的静态方法.currentThread().getName()循环的自增值 。,主线程创建自定义对象实例 。调用START()方法OK、 。
java多线程中的死循环是这样的java线程循环执行代码,ss.accept()方法是阻塞的java线程循环执行代码,也就是说ss所在的线程运行到accept()函数就会一直等待 , 直到ss接收到了一个Socket请求 。正因为accept()是阻塞的,所以一般会把这个函数放在一个单独的线程,这样就不会影响主线程(例如程序界面)的运行,Socket编程几乎是肯定和多线程编程一起用的 。accept()放进了单独的线程了自然就不会影响后面代码的执行 , 因为这时accept()的时间片和后续代码的时间片会由JVM调配,而不是按照代码编排的先后顺序了 。
另外java线程循环执行代码你对死循环的理解有偏差,所谓死循环是指循环条件永远为真而导致循环一直不结束,而由于循环内部的方法阻塞导致的循环不结束不属于死循环,这两个有本质的差别 。通常Socket.accept()是该放进一个死循环的,也就是你的while(true);
【java线程循环执行代码 java for循环 线程】java线程循环执行代码的介绍就聊到这里吧,感谢你花时间阅读本站内容 , 更多关于java for循环 线程、java线程循环执行代码的信息别忘了在本站进行查找喔 。
推荐阅读
- 苹果手机升级ios16屏幕变白,苹果更新后屏幕黑白怎么换
- 如何使用好wordpress,如何使用好手机网络部队
- 国外服务器叫什么原因,外国服务器有什么用
- 斗鱼怎么设置直播公告,斗鱼怎么设置直播公告提醒
- 怎么删除低版本mysql mysql怎么删除之前的数据库
- java代码画小动物,java画简单图形
- 安卓版微信图片大小限制,微信图片大小超过限制无法查看怎么办
- go语言快速入门教程02 go 语言教程
- redis是否可以存储图片,redis是否可以存储图片数据