每个线程是类 Thread的一个实例。有两个使用线程对象创建一个并发应用的策略。
直接创建和管理线程,每次应用需要开始一个异步任务时,简单的实例化Thread
从其余的应用抽象出线程管理,把应用任务传给executor。
这一段使用Thread对象。Executors在高级并发对象一段里讨论。
一个应用创建一个线程实例,必须提供一个运行在线程里代码。有两种方法:
实现一个Runnable对象,Runnable接口的只有一个方法run,用来包含线程的执行代码。Runnable的实现对象传给Thread构造器,如HelloRunnable所示:
public class HelloRunnable implements Runnable {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}
子类Thread。Thread类实现了Runnable,但它的run方法是空的。应用可以继承Thread,实现自己的run方法,如HelloThread所示:
public class HelloThread extends Thread {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new HelloThread()).start();
}
}
注意两种实现都是调用Thread.start开始一个线程。
这些方法应该使用哪个?第一种实现,用了一个Runnable的实现对象,更常用,因为Runnable实现对象能,因为Runnable实现对象还可以继承一个父类。第二种实现在简单应用中是简单的,但是必须是Thread的子类,这实际上是由限制的。这里主要集中在第一种方法,脱离Thread对象执行任务。这种方法不仅更灵活,而且适用于下面的高级线程管理。
Thread类定义了一些对线程管理有用的方法。包括提供相关信息的静态方法和影响线程状态的方法。还有用来管理线程和线程对象的被其他线程调用的方法。我们将在下面学些这些方法。
(二) 用sleep 暂停一个线程
Thread.sleep使线程在指定一段时间内暂停。这是一个有效的方法使处理器去处理其他线程或者其他应用。Sleep也可以用来步调(pacing),如下所示,和等待另一个线程的执行要求如下SimpleThreads例子。
提供了两个sleep的重载方法:一个用毫秒指定睡眠时间,另个指定纳秒。然而,这里的睡眠时间不保证精确,因为它被系统所限制。另外,睡眠可以被中断终止,我们在下面将看到例子。在任何情况下,你都不能假设你可以通过调用sleep精确的挂起线程。
SleepMessages例子用sleep每隔4秒打印信息:
public class SleepMessages {public static void main(String args[])throws InterruptedException {
String importantInfo[] = {
"Mares eat oats",
"Does eat oats",
"Little lambs eat ivy",
"A kid will eat ivy too"
};
for (int i = 0; i < importantInfo.length; i++) {
//Pause for 4 seconds
Thread.sleep(4000);
//Print a message
System.out.println(importantInfo[i]);
}
}
}
注意main方法声明抛出InterruptedException。这是当前线程sleep时被其他线程中断抛出的异常。因为这个应用没有定义另一个线程引起中断,所以不必费心去捕获。
中断是指一个线程正在做的事应该停止。它适用于程序员去正确的决定线程应该如何响应中断。但是通常情况是终止线程。这是这章强调的用法。
线程通过调用Thread对象中的interrupt方法发送interrupt使线程中断。为了使中断机制正确工作,中断的线程必须支持它自己的中断。
一个线程怎样支持自己中断呢?这个依 赖它当前在做什么。如果线程在调用方法时频繁的抛出异常,它会在捕获异常后从这个run方法中返回。比如,假设在SleepMessages例子中主要的 for循环是在一个线程的Runnable对象的run方法中。它可以改成下面这个以支持中断
for (int i = 0; i < importantInfo.length; i++) {
// Pause for 4 seconds
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
// We've been interrupted: no more messages.
return;
}
// Print a message
System.out.println(importantInfo[i]);
}
许多方法会抛出InterruptedException,比如sleep,被设计取消它们当前的操作并且当接受到中断时立即返回
如果线程很长时间没有调用会抛出InterruptedException异常的方法怎么样呢?这时可以定期的调用Thread.interrupted,如果接收到了中断它会返回true。
for (int i = 0; i < inputs.length; i++) {
heavyCrunch(inputs[i]);
if (Thread.interrupted()) {
// We've been interrupted: no more crunching.return;
}
}
在这个简单的例子里,代码简单的测试了中断和线程接收到中断的退出。在更复杂的应用程序中,可能要更加注意抛出InterruptedException异常
if (Thread.interrupted()) {
throw new InterruptedException();
}
这个允许中断处理代码集中在一个catch块里
中断机制是使用一个称作中断状态的内部标识来实现的。调用Thread.interrupt设置这个标识。当线程通过调用静态方法 Thread.interrupted检查中断时,中断状态会被清除。非静态的isInterrupted方法被用作一个线程查询另外一个线程的中断状 态,这个不会改变中断状态标识。
按照惯例,任何方法通过抛出异常退出会清除中断状态。然而,极可能中断状态会因为其他的线程调用interrupt而立即被再次设置。
join方法允许一个线程等得另个线程的完成。如果t是当前执行的一个线程对象,
t.join()
引起当前线程暂停,直到t线程终止。join的重载允许程序员指定一个等待时间。然而,和sleep一样,join的等待时间也是不精确的,所以你不要假设join方法会按照你指定的时间精确执行。
像sleep一样,join抛出一个InterruptedException响应中断请求。
下面的例子展示了这章的内容。SimpleThreads包含两个线程。第一个是每个java程序都有的main线程。Main线程通过Tunnable创建一个子线程MessageLoop,等待它的完成。如果MessageLoop执行时间太长,主线程中断它。
MessageLoop打印一些列信息。如果在它打印完所有信息之前中断,MessageLoop打印一个信息并退出。
public class SimpleThreads {
// Display a message, preceded by
// the name of the current thread
static void threadMessage(String message) {
String threadName =Thread.currentThread().getName();
System.out.format("%s: %s%n",threadName, message);
}
private static class MessageLoop implements Runnable {
public void run() {
String importantInfo[] = {"Mares eat oats","Does eat oats","Little lambs eat ivy","A kid will eat ivy too" };
try {
for (int i = 0; i < importantInfo.length; i++) {
// Pause for 4 seconds
Thread.sleep(4000);
// Print a message
threadMessage(importantInfo[i]);
}
} catch (InterruptedException e) {
threadMessage("I wasn't done!");
}
}
}
public static void main(String args[]) throws InterruptedException {
// Delay, in milliseconds before
// we interrupt MessageLoop
// thread (default one hour).
long patience = 1000 * 60 * 60;
// If command line argument
// present, gives patience
// in seconds.
if (args.length > 0) {
try {
patience = Long.parseLong(args[0]) * 1000;
} catch (NumberFormatException e) {
System.err.println("Argument must be an integer.");
System.exit(1);
}
}
threadMessage("Starting MessageLoop thread");
long startTime = System.currentTimeMillis();
Thread t = new Thread(new MessageLoop());
t.start();
threadMessage("Waiting for MessageLoop thread to finish");
// loop until MessageLoop
// thread exits
while (t.isAlive()) {
threadMessage("Still waiting...");
// Wait maximum of 1 second
// for MessageLoop thread
// to finish.
t.join(1000);
if (((System.currentTimeMillis() - startTime) > patience) && t.isAlive()) {
threadMessage("Tired of waiting!");
t.interrupt();
// Shouldn't be long now
// -- wait indefinitely
t.join();
}
}
threadMessage("Finally!");
}
}
分享到:
相关推荐
最后,Java并发库还包含了很多其他有用的工具,如Semaphore(信号量)用于控制同时访问特定资源的线程数量,CyclicBarrier(循环屏障)和CountDownLatch(计数器门锁)用于多线程间的协作,以及Lock接口及其实现如...
在Java编程中,多线程并发是提升程序执行效率、充分利用多核处理器资源的重要手段。本文将基于"java 多线程并发实例"这个主题,深入探讨Java中的多线程并发概念及其应用。 首先,我们要了解Java中的线程。线程是...
Java并发多线程是Java编程中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,多线程主要通过`Thread`类、`Runnable`接口以及`ExecutorService`来实现。下面我们将深入探讨...
Java并发编程线程入门主要涉及以下几个关键知识点: 1. **并发编程基础**:Java自诞生以来就支持并发编程,提供了一系列的机制来处理多任务执行。并发编程的主要目标是利用多核处理器的能力,同时执行多个任务,...
首先,Java并发编程的核心在于管理线程的并发执行。线程并发的使用可以显著提升程序处理能力,例如在服务器端处理大量用户请求时,如果每个请求都由单独的线程处理,那么处理速度将大大提高。但同时,多线程并发也会...
以上知识点覆盖了Java并发编程的主要方面,包括线程管理、同步机制、并发工具、设计模式、并发集合以及并发编程的最佳实践等,是理解和掌握Java并发编程的关键。在实际开发中,理解和熟练运用这些知识可以编写出高效...
在Java编程中,多线程是并发处理任务的关键技术,特别是在高性能、高并发的应用场景下。本篇将探讨“多线程结果组装”的主题,它涉及到如何在多个并发执行的任务完成后,有效地收集并整合这些任务的结果。这个过程...
总的来说,这份“java并发编程内部分享PPT”涵盖了Java并发编程的多个重要方面,包括线程创建与管理、同步机制、并发容器、线程池、并发问题以及异步计算。通过深入学习和实践这些知识点,开发者可以更好地应对多...
本文将详细探讨如何利用Java的多线程技术和线程池来实现并发查询数据库,以及相关的文件`BatchDataUtil.java`和`BatchDataRunnable.java`可能涉及的关键知识点。 ### 1. 多线程并发查询 多线程并发查询允许我们将一...
线程安全的数据结构,如ConcurrentHashMap、ConcurrentLinkedQueue等,是Java并发编程的重要组成部分。它们内部实现了线程安全的更新策略,能够在高并发环境下保证数据一致性。 异常处理在多线程编程中同样重要。...
本项目聚焦于使用Java的Socket进行多线程并发控制,并结合Hibernate ORM框架与MySQL数据库进行数据存储。下面将详细阐述这些技术及其应用。 首先,Java Socket是Java提供的用于实现网络上不同计算机间进程通信的...
《Java并发编程实践》是一本深入探讨Java多线程编程的经典著作,由Brian Goetz、Tim Peierls、Joshua Bloch、Joseph Bowles和David Holmes等专家共同编写。这本书全面介绍了Java平台上的并发编程技术,是Java开发...
#### 二、Java并发核心概念 在深入讨论具体技术细节之前,我们先了解一些关键的Java并发概念: 1. **Java Memory Model (JMM)**: - **定义**: 在Java SE 5 (JSR133)中引入的Java Memory Model (JMM)旨在确保编写...
### Java并发编程实战知识点概述 #### 一、Java并发特性详解 在《Java并发编程实战》这本书中,作者深入浅出地介绍了Java 5.0和Java 6中新增的并发特性。这些特性旨在帮助开发者更高效、安全地编写多线程程序。书中...
Java多线程与并发是Java编程中至关重要的一个领域,特别是在构建高性能、高并发的应用时。线程基础是理解并发编程的关键,它涉及到线程的状态转换、创建与使用方式、同步与协作机制等方面。 线程有五种基本状态: 1...
第二部分 结构化并发应用程序 第6章 任务执行 6.1 在线程中执行任务 6.1.1 串行地执行任务 6.1.2 显式地为任务创建线程 6.1.3 无限制创建线程的不足 6.2 Executor框架 6.2.1 示例:基于Executor的Web服务器 ...
Java并发编程是Java开发者必须掌握的关键技能之一,它涉及到如何在多线程环境中高效、安全地执行程序。并发编程能够充分利用多核处理器的计算能力,提高应用程序的响应速度和整体性能。《Java编程并发实战》这本书是...
### Java并发中的线程安全性 #### 1. 引言 随着Java技术的发展以及多核处理器的普及,Java并发编程成为软件开发中的一个重要领域。Java并发控制问题是国内外学者研究的热点之一,特别是在J2SE 1.5版本中引入了`...