`
leichenlei
  • 浏览: 127807 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java并发(二、线程对象)

    博客分类:
  • java
 
阅读更多

线程对象

每个线程是类 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();

    }

}

子类ThreadThread类实现了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使线程中断。为了使中断机制正确工作,中断的线程必须支持它自己的中断。

1.         支持中断

一个线程怎样支持自己中断呢?这个依 赖它当前在做什么。如果线程在调用方法时频繁的抛出异常,它会在捕获异常后从这个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块里

2.         中断状态标识

中断机制是使用一个称作中断状态的内部标识来实现的。调用Thread.interrupt设置这个标识。当线程通过调用静态方法 Thread.interrupted检查中断时,中断状态会被清除。非静态的isInterrupted方法被用作一个线程查询另外一个线程的中断状 态,这个不会改变中断状态标识。

按照惯例,任何方法通过抛出异常退出会清除中断状态。然而,极可能中断状态会因为其他的线程调用interrupt而立即被再次设置。

(四)           Joins

      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 模拟线程并发

    最后,Java并发库还包含了很多其他有用的工具,如Semaphore(信号量)用于控制同时访问特定资源的线程数量,CyclicBarrier(循环屏障)和CountDownLatch(计数器门锁)用于多线程间的协作,以及Lock接口及其实现如...

    java 多线程并发实例

    在Java编程中,多线程并发是提升程序执行效率、充分利用多核处理器资源的重要手段。本文将基于"java 多线程并发实例"这个主题,深入探讨Java中的多线程并发概念及其应用。 首先,我们要了解Java中的线程。线程是...

    超实用的Java并发多线程教程

    Java并发多线程是Java编程中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,多线程主要通过`Thread`类、`Runnable`接口以及`ExecutorService`来实现。下面我们将深入探讨...

    Java并发编程线程入门简介.pdf

    Java并发编程线程入门主要涉及以下几个关键知识点: 1. **并发编程基础**:Java自诞生以来就支持并发编程,提供了一系列的机制来处理多任务执行。并发编程的主要目标是利用多核处理器的能力,同时执行多个任务,...

    JAVA多线程并发编程

    首先,Java并发编程的核心在于管理线程的并发执行。线程并发的使用可以显著提升程序处理能力,例如在服务器端处理大量用户请求时,如果每个请求都由单独的线程处理,那么处理速度将大大提高。但同时,多线程并发也会...

    java并发编程2

    以上知识点覆盖了Java并发编程的主要方面,包括线程管理、同步机制、并发工具、设计模式、并发集合以及并发编程的最佳实践等,是理解和掌握Java并发编程的关键。在实际开发中,理解和熟练运用这些知识可以编写出高效...

    java并发(二十四)多线程结果组装

    在Java编程中,多线程是并发处理任务的关键技术,特别是在高性能、高并发的应用场景下。本篇将探讨“多线程结果组装”的主题,它涉及到如何在多个并发执行的任务完成后,有效地收集并整合这些任务的结果。这个过程...

    java并发编程内部分享PPT

    总的来说,这份“java并发编程内部分享PPT”涵盖了Java并发编程的多个重要方面,包括线程创建与管理、同步机制、并发容器、线程池、并发问题以及异步计算。通过深入学习和实践这些知识点,开发者可以更好地应对多...

    java多线程查询数据库

    本文将详细探讨如何利用Java的多线程技术和线程池来实现并发查询数据库,以及相关的文件`BatchDataUtil.java`和`BatchDataRunnable.java`可能涉及的关键知识点。 ### 1. 多线程并发查询 多线程并发查询允许我们将一...

    java线程与并发编程实践

    线程安全的数据结构,如ConcurrentHashMap、ConcurrentLinkedQueue等,是Java并发编程的重要组成部分。它们内部实现了线程安全的更新策略,能够在高并发环境下保证数据一致性。 异常处理在多线程编程中同样重要。...

    java socket 多线程并发控制 hibernate mysql

    本项目聚焦于使用Java的Socket进行多线程并发控制,并结合Hibernate ORM框架与MySQL数据库进行数据存储。下面将详细阐述这些技术及其应用。 首先,Java Socket是Java提供的用于实现网络上不同计算机间进程通信的...

    Java并发编程实践高清pdf及源码

    《Java并发编程实践》是一本深入探讨Java多线程编程的经典著作,由Brian Goetz、Tim Peierls、Joshua Bloch、Joseph Bowles和David Holmes等专家共同编写。这本书全面介绍了Java平台上的并发编程技术,是Java开发...

    Java 并发核心编程

    #### 二、Java并发核心概念 在深入讨论具体技术细节之前,我们先了解一些关键的Java并发概念: 1. **Java Memory Model (JMM)**: - **定义**: 在Java SE 5 (JSR133)中引入的Java Memory Model (JMM)旨在确保编写...

    java并发编程实战(英文版)

    ### Java并发编程实战知识点概述 #### 一、Java并发特性详解 在《Java并发编程实战》这本书中,作者深入浅出地介绍了Java 5.0和Java 6中新增的并发特性。这些特性旨在帮助开发者更高效、安全地编写多线程程序。书中...

    Java 多线程与并发(2-26)Java 并发 - 线程基础.pdf

    Java多线程与并发是Java编程中至关重要的一个领域,特别是在构建高性能、高并发的应用时。线程基础是理解并发编程的关键,它涉及到线程的状态转换、创建与使用方式、同步与协作机制等方面。 线程有五种基本状态: 1...

    Java并发编程实战

    第二部分 结构化并发应用程序 第6章 任务执行 6.1 在线程中执行任务 6.1.1 串行地执行任务 6.1.2 显式地为任务创建线程 6.1.3 无限制创建线程的不足 6.2 Executor框架 6.2.1 示例:基于Executor的Web服务器 ...

    java并发编程

    Java并发编程是Java开发者必须掌握的关键技能之一,它涉及到如何在多线程环境中高效、安全地执行程序。并发编程能够充分利用多核处理器的计算能力,提高应用程序的响应速度和整体性能。《Java编程并发实战》这本书是...

    Java并发中的线程安全性

    ### Java并发中的线程安全性 #### 1. 引言 随着Java技术的发展以及多核处理器的普及,Java并发编程成为软件开发中的一个重要领域。Java并发控制问题是国内外学者研究的热点之一,特别是在J2SE 1.5版本中引入了`...

Global site tag (gtag.js) - Google Analytics