java thread.join_浅析Java的Thread.join函数

(一)join参数解析

join(): 即join(0),主线程无限等待子进程结束,主线程方可执行。

join(long millis):主线程需等待子进程*毫秒,主线程方可执行。

(二)join源码

join函数用了synchronized关键字,即为同步,线程安全。

public final synchronized void join(long millis)

throws InterruptedException {

long base = System.currentTimeMillis();

long now = 0;

if (millis < 0) {

throw new IllegalArgumentException("timeout value is negative");

}

if (millis == 0) {

while (isAlive()) {

wait(0);

}

} else {

while (isAlive()) {

long delay = millis - now;

if (delay <= 0) {

break;

}

wait(delay);

now = System.currentTimeMillis() - base;

}

}

}

(三)join 案例分析

自定义线程函数,方便查看结果比较函数效果

public class ThreadJoin extendsThread {publicThreadJoin(String name) {super(name);

}

@Overridepublic voidrun(){for(int i=0;i<10;i++){

System.out.println("i:" + i + ", name:" + this.getName());

}

}

}

【测试一】.线程无join()

public class ThreadJoinTest {

public static void main(String [] args)throws InterruptedException {

ThreadJoin threadOne = new ThreadJoin("晓东");

ThreadJoin threadTwo = new ThreadJoin("小明");

System.out.println("---Test start---");

threadOne.start();

threadTwo.start();

System.out.println("---Test end---");

}

}

运行结果:

---Test start---

---Test end---i:0, name:晓东

i:0, name:小明

i:1, name:小明

i:2, name:小明

i:1, name:晓东

i:3, name:小明

i:4, name:小明

i:2, name:晓东

i:5, name:小明

i:6, name:小明

i:3, name:晓东

i:7, name:小明

i:4, name:晓东

i:5, name:晓东

i:6, name:晓东

i:7, name:晓东

i:8, name:晓东

i:9, name:晓东

i:8, name:小明

i:9, name:小明

总结:Main线程先执行,然后threadOne和threadTwo子进程随机执行,当谁抢占CPU资源的时候,即执行System.out.println("i:" + i + ", name:" + this.getName())。由于线程抢占资源

不确定性,所以两个子进程的执行顺序不一,重复运行的结果也不一样。

【测试二】.线程join()

public class ThreadJoinTest {

public static void main(String [] args)throws InterruptedException {

ThreadJoin threadOne = new ThreadJoin("晓东");

ThreadJoin threadTwo = new ThreadJoin("小明");

System.out.println("---Test start---");

threadOne.start();

threadTwo.start();

threadOne.join();

threadTwo.join();

System.out.println("---Test end---");

}

}

运行结果:

---Test start---

i:0, name:晓东

i:0, name:小明

i:1, name:小明

i:2, name:小明

i:1, name:晓东

i:3, name:小明

i:2, name:晓东

i:3, name:晓东

i:4, name:小明

i:4, name:晓东

i:5, name:小明

i:5, name:晓东

i:6, name:小明

i:6, name:晓东

i:7, name:晓东

i:8, name:晓东

i:9, name:晓东

i:7, name:小明

i:8, name:小明

i:9, name:小明

---Test end---

总结:可以看出Main主进程先执行start,然后执行两个子进程,最后执行Main主进程的end。所以这个可以看出,主线程必须等到子进程都结束后,才执行。同样子进程的运行顺序也是不一样的。

这里需要注意下,子进程的join()是让正在运行的父亲进程(即Main主进程)进入等待,而不是new thread的子进程进入等待。即让正在运行的进程进入等待。

【测试三】.线程join()在子进程开始运行之前和开始运行之后是否有差异

public class ThreadJoinTest {

public static void main(String [] args)throws InterruptedException {

ThreadJoin threadOne = new ThreadJoin("晓东");

ThreadJoin threadTwo = new ThreadJoin("小明");

System.out.println("---Test start---");

threadOne.join();

threadTwo.join();

threadOne.start();

threadTwo.start();

System.out.println("---Test end---");

}

}

运行结果:

---Test start---

---Test end---

i:0, name:晓东

i:0, name:小明

i:1, name:晓东

i:1, name:小明

i:2, name:晓东

i:3, name:晓东

i:2, name:小明

i:4, name:晓东

i:3, name:小明

i:4, name:小明

i:5, name:小明

i:5, name:晓东

i:6, name:小明

i:6, name:晓东

i:7, name:小明

i:7, name:晓东

i:8, name:小明

i:8, name:晓东

i:9, name:小明

i:9, name:晓东

总结:可以看出运行结果和无join()的【测试一】是一样的。所以start()前执行join()无效,类似于只执行start()

【测试四】join()和join(**)区别

代码一:

public class ThreadJoin extends Thread {

public ThreadJoin(String name) {

super(name);

}

@Override

public void run(){

for(int i=0;i<100;i++){

System.out.println("i:" + i + ", name:" + this.getName());

}

}

}

public class ThreadJoinTest {

public static void main(String [] args)throws InterruptedException {

ThreadJoin threadOne = new ThreadJoin("晓东");

ThreadJoin threadTwo = new ThreadJoin("小明");

System.out.println("---Test start---");

threadOne.start();

threadTwo.start();

threadOne.join(0);

System.out.println("---Test end---");

}

}

代码二:

public class ThreadJoin extendsThread {publicThreadJoin(String name) {super(name);

}

@Overridepublic voidrun(){for(int i=0;i<100;i++){

System.out.println("i:" + i + ", name:" + this.getName());

}

}

}public classThreadJoinTest {public static void main(String [] args)throwsInterruptedException {

ThreadJoin threadOne= new ThreadJoin("晓东");

ThreadJoin threadTwo= new ThreadJoin("小明");

System.out.println("---Test start---");

threadOne.start();

threadTwo.start();

threadOne.join(1);

System.out.println("---Test end---");

}

}

代码二运行结果:

---Test start---i:0, name:晓东

i:0, name:小明

i:1, name:小明

i:2, name:小明

i:1, name:晓东

i:3, name:小明

i:2, name:晓东

i:4, name:小明

i:3, name:晓东

i:5, name:小明

i:4, name:晓东

i:6, name:小明

i:5, name:晓东

i:7, name:小明

i:8, name:小明

i:9, name:小明

i:10, name:小明

i:6, name:晓东

i:11, name:小明

i:7, name:晓东

i:8, name:晓东

i:9, name:晓东

i:10, name:晓东

i:11, name:晓东

i:12, name:晓东

i:12, name:小明

i:13, name:晓东

i:13, name:小明

i:14, name:小明

i:15, name:小明---Test end---i:14, name:晓东

i:16, name:小明

i:15, name:晓东

i:17, name:小明

i:16, name:晓东

i:18, name:小明

...

运行结果:不一样。

代码一:先执行主线程start,然后执行两个子线程,最后执行主线程end。

代码二:先执行主线程start,然后执行两个子线程部分,主线程睡眠1毫秒唤醒后,执行主线程end,再执行两个子线程剩下部分。

总结:join()无限等待子进程结束, join(*毫秒)主线程只是等待子进程*毫秒。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用QTimer对象代替QBasicTimer对象,修改程序class MyWindow(QWidget): def init(self): super().init() self.thread_list = [] self.color_photo_dir = os.path.join(os.getcwd(), "color_photos") self.depth_photo_dir = os.path.join(os.getcwd(), "depth_photos") self.image_thread = None self.saved_color_photos = 0 # 定义 saved_color_photos 属性 self.saved_depth_photos = 0 # 定义 saved_depth_photos 属性 self.init_ui() def init_ui(self): self.ui = uic.loadUi("C:/Users/wyt/Desktop/D405界面/intelrealsense1.ui") self.open_btn = self.ui.pushButton self.color_image_chose_btn = self.ui.pushButton_3 self.depth_image_chose_btn = self.ui.pushButton_4 self.open_btn.clicked.connect(self.open) self.color_image_chose_btn.clicked.connect(lambda: self.chose_dir(self.ui.lineEdit, "color")) self.depth_image_chose_btn.clicked.connect(lambda: self.chose_dir(self.ui.lineEdit_2, "depth")) def open(self): self.profile = self.pipeline.start(self.config) self.is_camera_opened = True self.label.setText('相机已打开') self.label.setStyleSheet('color:green') self.open_btn.setEnabled(False) self.close_btn.setEnabled(True) self.image_thread = ImageThread(self.pipeline, self.color_label, self.depth_label, self.interval, self.color_photo_dir, self.depth_photo_dir, self._dgl) self.image_thread.saved_color_photos_signal.connect(self.update_saved_color_photos_label) self.image_thread.saved_depth_photos_signal.connect(self.update_saved_depth_photos_label) self.image_thread.start() def chose_dir(self, line_edit, button_type): my_thread = MyThread(line_edit, button_type) my_thread.finished_signal.connect(self.update_line_edit) self.thread_list.append(my_thread) my_thread.start()
05-26

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值