博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Computer Science III Thread
阅读量:4974 次
发布时间:2019-06-12

本文共 5701 字,大约阅读时间需要 19 分钟。

在java中可有两种方式实现多线程:

1. 继承Thread类
2. 是实现Runnable接口

由于Java不支持多继承,所以推荐使用实现Runnable接口的方法。

如果想要新建一个线程类,那么只需要override run() method就好了。

实现Runnable的类在创建新线程的时候用 Tread tread = new Tread(实现Runnable接口的类),就完成了Tread的创建。

 

 

 - State transitions of a thread

Thread类的两个主要method: start() 和 run()的区别

start() 

  - 让thread进入 runnable 状态
  - call run() method
  - extend Thread Class不用override start() method

run()

  - 当thread运行时被调用
  - run()在thread创建完了之后被调用
  - Runnable类里的run()没有任何内容,所以一定要实现

 

  • GUI和Threads

  在Java中,GUI的绘制和事件的处理都是集中在一个线程之中完成的,这个线程叫做Event Dispatcher Thread - 事件分发线程 简称EDT

  我在CSDN上发现了一个关于Swing EDT的很好的文章  

  "EDT:Swing程序只有一个EDT,该线程负责GUI组件的绘制和更新,通过调用程序的事件处理器来响应用户交互。所有事件处理都是在EDT上进行的,程序同UI组件和其基本数据模型的交互只允许在EDT上进行,所有运行在EDT上的任务应该尽快完成,以便UI能及时响应用户输入。"
  简单来说EDT机制是为了防止GUI的绘制和事件互相影响(interrupted)。

  为什么要在这里谈到EDT呢?

  因为下面一个概念不是很好理解(至少javadoc写得很模糊): Platform.runLater(): 如果你有多个线程,其中包括一个GUI线程(也就是EDT),一个是没有GUI的线程。比如说你需要完成一个进度条,但是如何才能让进度(非GUI线程)和进度条(GUI线程)相互关联呢?那么Platform.runlater()就很有用了。

  Platform.runlater()的具体实现也有主要两种方法,比如说我们想要创建一个从1数到1,000,000的进度条:

  第一种写法是这样的:

Code using PlatForm.RunLater :

final ProgressBar bar = new ProgressBar();new Thread(new Runnable() {    @Override public void run() {        for (int i=1; i<=1000000; i++) {            final int counter = i;            Platform.runLater(new Runnable() {                @Override public void run() {                    bar.setProgress(counter/1000000.0);                }            });        }    }}).start();

第一种写法其实是一种很反人类的写法,你的脑子会因为两个Runnable多死几个细胞!

 

第二种实现是:

Code using Task :

Task task = new Task
() { @Override public Void run() { static final int max = 1000000; for (int i=1; i<=max; i++) { updateProgress(i, max); } return null; }};ProgressBar bar = new ProgressBar();bar.progressProperty().bind(task.progressProperty());new Thread(task).start();

这样的写法就简洁很多。

具体的讨论详见stackoverflow: 

 

但不是说我们不能用Platform.runlater(),下面是一个使用Platform.runlater()实现进度条的例子。

import java.util.concurrent.locks.ReentrantLock;import javafx.application.Application;import static javafx.application.Application.launch;import javafx.application.Platform;import javafx.concurrent.Task;import javafx.scene.Scene;import javafx.scene.control.Button;import javafx.scene.control.Label;import javafx.scene.control.ProgressBar;import javafx.scene.control.ProgressIndicator;import javafx.scene.layout.HBox;import javafx.scene.layout.VBox;import javafx.scene.text.Font;import javafx.stage.Stage;public class BetterProgressTest extends Application {    ProgressBar bar;    ProgressIndicator indicator;    Button button;    Label processLabel;    int numTasks = 0;    ReentrantLock progressLock;    @Override    public void start(Stage primaryStage) throws Exception {        progressLock = new ReentrantLock();        VBox box = new VBox();        HBox toolbar = new HBox();        bar = new ProgressBar(0);              indicator = new ProgressIndicator(0);        toolbar.getChildren().add(bar);        toolbar.getChildren().add(indicator);                button = new Button("Restart");        processLabel = new Label();        processLabel.setFont(new Font("Serif", 36));        box.getChildren().add(toolbar);        box.getChildren().add(button);        box.getChildren().add(processLabel);                Scene scene = new Scene(box);        primaryStage.setScene(scene);        button.setOnAction(e -> {                Task
task = new Task
() { int task = numTasks++; double max = 200; double perc; @Override protected Void call() throws Exception { try { progressLock.lock(); for (int i = 0; i < 200; i++) { System.out.println(i); perc = i/max; // THIS WILL BE DONE ASYNCHRONOUSLY VIA MULTITHREADING Platform.runLater(new Runnable() { @Override public void run() { bar.setProgress(perc); indicator.setProgress(perc); processLabel.setText("Task #" + task); } }); // SLEEP EACH FRAME //try {
Thread.sleep(10); // } catch (InterruptedException ie) { // ie.printStackTrace(); // } }} finally { progressLock.unlock(); } return null; } }; // THIS GETS THE THREAD ROLLING Thread thread = new Thread(task); thread.start(); }); primaryStage.show(); } public static void main(String[] args) { launch(args); }}
BetterProgressTest

  例子里面用到了Task类,关于Java并发的内容并不是很熟悉,就不深入研究了。

 

如何结果(kill)掉一个线程?

  常见的做法是设置一些条件(loop, exception)来让thread在运行达到一定结果之后终止(自我毁灭)。

 

  • Timer和TimerTask 用来创建和时间相关的类

  - Need program to do something X times/second

  - TimerTask可以看做第三种实现线程的方式(extend threads 和 implement Runnable之外)
    "Timer和TimerTask可以做为实现线程的第三种方式,前两中方式分别是继承自Thread类和实现Runnable接口。
    Timer是一种线程设施,用于安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行,可以看成一个定时器,可以调度TimerTask。TimerTask是一个抽象类,实现了Runnable接口,所以具备了多线程的能力。"  

转载于:https://www.cnblogs.com/zeqli/p/4371221.html

你可能感兴趣的文章
Python HDB3 AMI 编码与解码
查看>>
jquery,fn,extend和jquery.extend
查看>>
js奇葩错误
查看>>
poj 3974 Palindrome
查看>>
等比例缩放图片
查看>>
实现笛卡尔心形线的重复循环绘制
查看>>
实验报告四
查看>>
JS学习笔记——标准对象
查看>>
南柯一梦
查看>>
生产者与消费者——厨师和消费者之间的问题
查看>>
选择排序
查看>>
将摄像头原始RGB数据流编码成H.264文件
查看>>
gcc中预定义的宏__GNUC__
查看>>
idea-自定义Java模板文件
查看>>
Eclipse快捷键 10个最有用的快捷键
查看>>
sort qort函数
查看>>
maven的导入
查看>>
(一)Jmeter 简单的录制
查看>>
旋转菜单
查看>>
Masonry介绍与使用实践(快速上手Autolayout)(转)
查看>>