`

并发编程(一)

 
阅读更多
用并发解决的问题大体上可以分为“速度”和“设计可管理性”两种。

在run()中对静态方法Thread.yield()的调用是对线程调度器(java线程机制的一部分,可以将CPU从一个线程转移给另一个线程)的一种建议,它在声明:我已经执行完生命周期中最重要的部分了,此刻正是切换给其他任务执行一段时间的大好时机。ps:其实就是我停会,让别的线程运行会。

将Runnable对象转化为工作任务的传统方式是把它提交给一个Thread构造器,下面是例子:
Thread t = new Thread(new LiftOff());
    t.start();

Thread构造器只需要一个Runnable对象。调用Thread对象的start()方法为该线程执行必须的初始化操作,然后调用Runnable的run()方法,以便在这个新线程中启动该任务。

使用Executor

Executor允许你管理异步任务的执行。我们可以使用Executor来代替上面的Thread对象。LiftOff对象知道如何运行具体的任务,与命令模式一样,它暴露了要执行的单一方法。
ExecutorService exec = Executors.newCachedThreadPool();
    for(int i = 0; i < 5; i++)
      exec.execute(new LiftOff());
      exec.shutdown();

非常常见的情况是,单个的Executor被用来创建和管理系统中所有任务。

对shutdown()方法的调用可以防止新任务被提交给这个Executor,当前线程将继续运行在shutdown被调用之前提交的所有任务。这个程序将在Executor中的所有任务完成之后尽快推出。

你可以很容易地将前面示例中的CachedThreadPool替换为不同类型的Executor。FixedThreadPool使用了有限的线程集来执行所提交的任务:
ExecutorService exec = Executors.newFixedThreadPool(5);
    for(int i = 0; i < 5; i++)
      exec.execute(new LiftOff());
    exec.shutdown();

从任务中产生返回值

Runnable是执行工作的独立任务,但是它不返回任何值。如果你希望任务在完成时能够返回一个值,那么可以实现Callable接口而不是Runnable接口。在java se5中引入的Callable是一种具有类型参数的泛型,它的类型参数表示的是从方法call(),中返回值,并且必须使用ExecutorService.submit()方法调用它:
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 CallableDemo {
  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)));
    for(Future<String> fs : results)
      try {
        // get() blocks until completion:
        System.out.println(fs.get());
      } catch(InterruptedException e) {
        System.out.println(e);
        return;
      } catch(ExecutionException e) {
        System.out.println(e);
      } finally {
        exec.shutdown();
} }
}

submit()方法会长生Future对象,它用Callable返回结果的特定类型进行了参数化。你可以使用isDone()方法来查询Future是否已经完成。

你可以使用Thread.currentThread()来获取当前该任务的Thread对象。

注意优先级是在run()的开头部分设定的,在构造器中设置它们不会有任何好处,因为Executor在此刻还没有开始执行任务。

虽然JDK有10个优先级,但是它与多数操作系统都不能映射得很好。唯一可一直的方法是当调整优先级的时候,只使用MAX_PRIORITY NORM_PRIORITY和MIN_PRIORITY

对于任何重要的控制或在调整应用时,都不能依赖与yield()。实际上,yield()经常被误用。

所谓后台线程,是指在程序运行的时候在后台提供一种通用服务的线程,并且这种线程并不属于程序中不可或缺的部分。因此,当所有的非后台线程结束时,程序也就终止了,同时会杀死进程中的所有后台线程。
for(int i = 0; i < 10; i++) {
      Thread daemon = new Thread(new SimpleDaemons());
      daemon.setDaemon(true); // Must call before start()
      daemon.start();
    }

必须在线程启动之前调用setDaemon()方法,才能把它设置为后台线程。

Daemon线程被设置成了后台模式,然后派生出许多子线程,这些线程并没有被显示地设置为后台模式,不过它们的确是后台线程。接着,Daemon线程进入了无限循环,并在循环里调用了yield()方法把控制权交给其他进程。

你应该意识到后台进程在不执行finally子句的情况下就会终止其run()方法。

当最后一个非后台线程终止时,后台线程会突然终止。

Runnable接口的名字选择很糟糕,所以我认为Task应该是好得多的名字。

加入一个线程

一个线程可以在其他线程之上调用join()方法,其效果是等待一段时间直到第二个线程结束才继续执行。如果某个线程在另一个线程t上调用t.join(),此线程将被挂起,直到目标线程t结束才恢复(即t.isAlive() == false)

也可以在调用join()时带上一个超时参数。

import static net.mindview.util.Print.*;
class Sleeper extends Thread {
  private int duration;
  public Sleeper(String name, int sleepTime) {
    super(name);
    duration = sleepTime;
    start();
  }
  public void run() {
    try {
      sleep(duration);
    } catch(InterruptedException e) {
      print(getName() + " was interrupted. " +
        "isInterrupted(): " + isInterrupted());
      return;
}
    print(getName() + " has awakened");
  }
}
class Joiner extends Thread {
  private Sleeper sleeper;
  public Joiner(String name, Sleeper sleeper) {
    super(name);
    this.sleeper = sleeper;
    start();
  }
  public void run() {
   try {
      sleeper.join();
    } catch(InterruptedException e) {
      print("Interrupted");
    }
    print(getName() + " join completed");
  }
}
public class Joining {
  public static void main(String[] args) {
    Sleeper
      sleepy = new Sleeper("Sleepy", 1500),
      grumpy = new Sleeper("Grumpy", 1500);
    Joiner
      dopey = new Joiner("Dopey", sleepy),
      doc = new Joiner("Doc", grumpy);
    grumpy.interrupt();
  }
} /* Output:
Grumpy was interrupted. isInterrupted(): false
Doc join completed
Sleepy has awakened
Dopey join completed


joiner线程将通过在Sleeper对象上调用join()方法来等待Sleeper醒来。在main()里面,每个Sleeper都有一个Joiner,这可以在输出中发现,如果Sleeper被中断或者是正常结束,Joiner将和Sleeper一同结束。

注意,Java SE5的java.util.concurrent类库包含诸如CyclicBarrier这样的工具,它们可能比最初的线程类库中的join()更加合适。

继续错误的代价由别人来承担,而承认错误的代价由自己来承担。

所有对象都自动含有单一的锁,当在对象上调用其任意synchronized方法的时候,此对象都被加锁,这时候对象上的其他synchronized方法只有等到前一个方法调用完毕并释放了锁之后才能被调用。其所有synchronized方法共享同一个锁。
分享到:
评论

相关推荐

    java并发编程实战源码,java并发编程实战pdf,Java

    《Java并发编程实战》是Java并发编程领域的一本经典著作,它深入浅出地介绍了如何在Java平台上进行高效的多线程编程。这本书的源码提供了丰富的示例,可以帮助读者更好地理解书中的理论知识并将其应用到实际项目中。...

    Java 并发编程实战.pdf

    作者可能还会分享如何测试和调试并发程序,这是并发编程中非常困难且容易被忽视的一部分。包括性能分析、死锁检测以及如何使用日志和监控工具来诊断并发程序中的问题。 此外,该书可能会对Java中一些新的并发API...

    java并发编程艺术

    并发编程是现代多核处理器环境下提升软件性能的关键手段,而Java语言提供了丰富的工具和API来支持这一领域。本书旨在帮助开发者理解和掌握如何在Java应用程序中有效地实现并行处理。 并发编程的核心概念包括线程、...

    java并发编程2

    Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。以下是对标题和描述中所提及的几个知识点的详细解释: 1. **线程与并发** - **线程*...

    《java 并发编程实战高清PDF版》

    《Java并发编程实战》是一本深入探讨Java平台并发编程的权威指南。这本书旨在帮助开发者理解和掌握在Java环境中创建高效、可扩展且可靠的多线程应用程序的关键技术和实践。它涵盖了从基本概念到高级主题的广泛内容,...

    Java高并发编程,构建并发编程知识体系,提升面试成功率

    Java高并发编程,构建并发编程知识体系,提升面试成功率,完整版17章视频教程下载。 本课程将结合大量图示及代码演示,带你掌握多线程并发编程(线程安全,线程调度,线程封闭,同步容器等)与高并发处理思路与手段...

    深入理解并发编程

    并发编程是计算机科学中的一个复杂领域,它涉及到同时运行多个任务,以提高程序的性能和效率。它在现代多核处理器和多处理器计算环境中尤其重要,因为这些环境允许并行执行多个计算。并发编程可以用于操作系统、...

    汪文君高并发编程实战视频资源下载.txt

    │ 高并发编程第一阶段01讲、课程大纲及主要内容介绍.wmv │ 高并发编程第一阶段02讲、简单介绍什么是线程.wmv │ 高并发编程第一阶段03讲、创建并启动线程.mp4 │ 高并发编程第一阶段04讲、线程生命周期以及...

    Java并发编程实战华章专业开发者书库 (Tim Peierls 等 美Brian Goetz).pdf

    《Java并发编程实战》是一本深入探讨Java平台并发编程的权威指南,由Tim Peierls等人与Brian Goetz合著,旨在帮助Java开发者理解和掌握在多线程环境中编写高效、安全的代码。这本书由拥有丰富经验的JDK并发大师及...

    java 并发编程的艺术pdf清晰完整版 源码

    并发编程是现代计算机系统中不可或缺的一部分,尤其是在多核处理器成为主流的今天。Java语言提供了丰富的并发工具和API,如线程、守护线程、线程池、同步机制(synchronized、wait/notify)、并发集合...

    JAVA并发编程艺术pdf版

    《JAVA并发编程艺术》是Java开发者深入理解和掌握并发编程的一本重要著作,它涵盖了Java并发领域的核心概念和技术。这本书详细阐述了如何在多线程环境下有效地编写高效、可靠的代码,对于提升Java程序员的技能水平...

    C++并发编程实践 C++ Concurrency in Action

    #### 一、简介与并发编程基础 《C++并发编程实践》这本书由Anthony Williams编写,是一本深入讲解C++多线程编程技术的专业书籍。本书旨在帮助读者掌握C++中的并发编程技巧,并通过大量的示例代码来加深理解。 **...

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

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

    java并发编程书籍

    Java并发编程是软件开发中的一个关键领域,尤其是在大型企业级应用和分布式系统中。通过学习相关的书籍,开发者可以深入理解如何有效地设计和实现高效的多线程应用程序,避免并发问题,如竞态条件、死锁、活锁等。...

    java并发编程实战中文加英文版加源码

    Joseph Bowbeer是一个Java ME专家,他对并发编程的兴趣始于Apollo计算机时代。David Holmes是《The Java Programming Language》一书的合著者,任职于Sun公司。Joshua Bloch是Google公司的首席Java架构师,...

    JAVA并发编程实践.pdf+高清版+目录 书籍源码

    总的来说,《JAVA并发编程实践》是一本深度和广度兼备的并发编程指南,无论是初学者还是有经验的Java开发者,都能从中受益匪浅。通过学习这本书,你将能够有效地应对并发编程中的挑战,提升你的多线程编程能力。

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

    综上所述,《Java并发编程实战》不仅涵盖了Java并发编程的基础知识和技术细节,还包含了丰富的实践经验和前瞻性的思考,是任何一位从事Java开发工作的程序员不可或缺的学习资源。无论是初学者还是有经验的开发者都能...

    java并发编程内部分享PPT

    这份“java并发编程内部分享PPT”显然是一个深入探讨这一主题的资料,旨在帮助开发者理解并掌握Java并发编程的核心概念和技术。 在Java并发编程中,首先我们需要了解的基本概念是线程。线程是操作系统分配CPU时间的...

Global site tag (gtag.js) - Google Analytics