JAVA学习笔记 -- 线程

来源:互联网 发布:与淘宝打假师聊天方案 编辑:程序博客网 时间:2024/05/19 21:43

之前学习的都是关于顺序编程的知识,程序在任意时刻都只能执行一个步骤。线程作为我接触并发编程的第一堂课,我感觉很兴奋。

1、定义任务

    实现Runnable接口并编写run()方法(线程将会执行此方法内代码)。

class LiftOff implements Runnable {  protected int countDown = 10;private static int taskCount = 0;private final int id = taskCount++;public LiftOff() {}public LiftOff(int countDown) {this.countDown = countDown;}public String status() {return "#" + id + "("+ (countDown > 0 ? String.valueOf(countDown) : "Liftoff!")+ "),";}public void run() {while (countDown-- > 0) {System.out.print(status());Thread.yield();}System.out.println();}}public class ThreadTest {public static void main(String[] args) {LiftOff launch = new LiftOff();launch.run();}}/* * Output: #0(9),#0(8),#0(7),#0(6),#0(5),#0(4),#0(3),#0(2),#0(1),#0(Liftoff!), */// :~
如上代码,从Runnable导出一个类,再调用它的run()方法,但这个方法不会产生任何内在的线程能力。

要实现线程行为,必须将它附着到线程上。


2、创建和启动线程

A. 通过Thread构造器。将Runnable对象提交给一个Thread构造器,再调用Thread对象的start()方法启动线程。

public class ThreadTest {public static void main(String[] args) {Thread t = new Thread(new LiftOff());t.start();System.out.println("Waiting for LiftOff");}}/* * Output: Waiting for LiftOff * #0(9),#0(8),#0(7),#0(6),#0(5),#0(4),#0(3),#0(2),#0(1),#0(Liftoff!), */// :~
在main()线程中,start()迅速的返回,此时子线程t执行的LiftOff.run()任务还未结束。这时两个线程并发运行,通过输出也可以看出。


B. 使用Executor。Executor是java.util.concurrent包中的执行器,可以更好的管理Thread对象。

a. CachedThreadPool,为每个任务都创建一个线程。

b. FixedThreadPool,使用有限的线程集来执行所提交的任务。

c. SingeThreadExecutor,如线程数量为1的FixedThreadPool。

public class ThreadTest {public static void main(String[] args) {ExecutorService exec1 = Executors.newCachedThreadPool();ExecutorService exec2 = Executors.newFixedThreadPool(5);//线程集限制数目为5ExecutorService exec3 = Executors.newSingleThreadExecutor();exec1.execute(new LiftOff());exec1.shutdown();//防止新任务被提交给这个Executors}}

3、Callable接口

Runnable是执行工作的独立任务,但它没有返回值。而Callable可以从任务中产生返回值。

下面代码展示它的用法:

import java.util.concurrent.*;import java.util.*;class TaskWithResult implements Callable<String> {private int id;public TaskWithResult(int id) {this.id = id;}public String call() {return "result of TaskWithResult " + id;}}public class ThreadTest {public static void main(String[] args) {ExecutorService exec = Executors.newCachedThreadPool();ArrayList<Future<String>> results = new ArrayList<Future<String>>();for (int i = 0; i < 10; i++) {results.add(exec.submit(new TaskWithResult(i)));// Callable的调用方式必须是 ExecutorService.submit(),// 同时submit()会产生一个Future对象,可以通过isDone()查询Future是否完成,通过get()获取call()的返回值.}for (Future<String> fs : results)try {System.out.print(fs.get() + ",");} catch (InterruptedException e) {System.out.println(e);return;} catch (ExecutionException e) {System.out.println(e);} finally {exec.shutdown();}}}/* * Output: result of TaskWithResult 0,result of TaskWithResult 1,result of * TaskWithResult 2,result of TaskWithResult 3,result of TaskWithResult 4,result * of TaskWithResult 5,result of TaskWithResult 6,result of TaskWithResult * 7,result of TaskWithResult 8,result of TaskWithResult 9, */// :~


4、线程相关方法和知识

a. yield(),表示当前线程已经完成或暂时不需要CPU,其它线程可以占用之,这只是个建议。

b. 优先级,通过getPriority()和setPriority()方法获取和重置线程的优先级,优先级和多数操作系统都不能映射的很好,唯一可移植的是设置优先级时,只使用 MAX_PRIORITY、NORM_PRIORITY和MIN_PRIORITY三个级别。

c. deamon(后台线程),它是程序运行的时候在后台提供的一种通用服务的线程,当所有非后台线程结束时,程序会杀死所有后台线程。

设置成后台线程的方法是:必须在线程启动前调用 setDaemon(true),后台线程派生出来的子线程都是后台线程。

d. join(),如果某个线程在另一个线程t上调用t.join(),此线程会被挂起,直到目标线程t结束才可恢复(即t.isAlive()返回为false)。





+待添加




4 0
原创粉丝点击