Fork me on GitHub
Mao's Blog

  • 首页

  • 归档

  • 分类

  • 标签

  • Java编程思想

  • Java并发编程实战

  • 搜索

Java并发编程实战———任务执行

发表于 2018-12-12 | 分类于 Java | 本文字数: 12k | 阅读时长 ≈ 0:19

在线程中执行任务

串行地执行任务

1
2
3
4
5
6
7
8
9
10
//串行的Web服务器
class SingleThreadWebServer {
public static void main(String[] args) throws IOException {
ServerSocket socket = new ServerSocket(80);
while(true) {
Socket connection = socket.accept();
handleRequest(connection);
}
}
}

显式地为任务创建线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
在Web服务器中为每个请求启动一个新的线程(不要这样做)
class ThreadPerTaskWebServer {
public static void main(String[] args) throws IOException {
ServerSocket socket = new ServerSocket(80);
while(true) {
final Socket connection = socket.accept();
Runnable task = new Runnable() {
public void run() {
handleRequest(connection);
}
}
new Thread(task).start();
}
}
}
  • 任务处理过程从主线程中分离出来,使得主循环能够更快地重新等待下一个到来的连接。这使得程序在完成前面的请求之前可以接受新的请求,从而提高响应性。
  • 任务可以并行处理,从而能够同时服务多个请求。
  • 任务处理代码必须是线程安全的,因为当有多个任务时会并发地调用这段代码。
阅读全文 »

Java并发编程实战———基础构建模块

发表于 2018-12-09 | 分类于 Java | 本文字数: 8.1k | 阅读时长 ≈ 0:14

Java平台类库包含了丰富的并发基础构建模块,例如线程安全的容器类以及各种用于协调多个相互协作的线程控制流的同步工具类(Synchronizer)。

同步容器类

同步容器类包括Vector和HashTable,还包括由Collections.synchronizedXxx等工厂方法创建的封装器类。同步容器类可以简单地理解为通过synchronized来实现同步的容器。这些类实现线程安全的方式是:将它们的状态封装起来,并对每个公有方法都进行同步,使得每次只有一个线程能访问容器的状态。

同步容器类的问题

同步容器类都是线程安全的,但在某些情况下可能需要额外的客户端加锁来保护复合操作。容器上常见的复合操作包括:迭代、跳转以及条件运算。在同步容器类中,这些复合操作在没有客户端加锁的情况下仍然是线程安全的,但当其他线程并发地修改容器时,它们可能会表现出意料之外的行为。

阅读全文 »

Java并发编程实战———ThreadLocal深度解析

发表于 2018-12-06 | 分类于 Java | 本文字数: 2.7k | 阅读时长 ≈ 0:04

ThreadLocal提供了线程的局部变量,每个线程都可以通过set()和get()来对这个局部变量进行操作,但不会和其他线程的局部变量进行冲突,实现了线程的数据隔离。

如何使用ThreadLocal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Main {
private ThreadLocal<Integer> threadLocal = new ThreadLocal<>();

public void start() {
for(int i=0; i<10; i++) {
new Thread(new Runnable() {
@override
public void run() {
threadLocal.set(i);
threadLocal.get();
threadLocal.remove();
}
}).start();
}
}
}

首先需要创建一个线程共享的ThreadLocal对象,该对象用于存储Integer类型的值,然后在每条线程中调用以下方法操作ThreadLocal:

  • set(obj):向当前线程中存储数据
  • get():获取当前线程中的数据
  • remove():删除当前线程中的数据
阅读全文 »

Java并发编程实战———对象的共享

发表于 2018-12-04 | 分类于 Java | 本文字数: 2k | 阅读时长 ≈ 0:03

可见性

为了确保多个线程之间对内存写入操作的可见性,必须使用同步机制。

非原子的64位操作

Java内存模型要求,变量的读取操作和写入操作都必须是原子操作,但对于非volatile类型的double和long变量,JVM允许将64位的读操作或写操作分解为两个32位的操作。当读取一个非volatile类型的long变量时,如果对该变量的读操作和写操作在不同的线程中执行,那么很可能会读取到某个值的高32位和另一个值的低32位。因此,即使不考虑失效数据问题,在多线程程序中使用共享且可变的long和double等类型的变量也是不安全的,除非用关键字volatile来声明它们,或者用锁保护起来。

阅读全文 »

Java编程思想———泛型

发表于 2018-12-02 | 分类于 Java | 本文字数: 2.8k | 阅读时长 ≈ 0:05

泛型实现了参数化类型的概念。

根据泛型应用的不同,可分为:

  • 泛型类

    1
    2
    3
    class ClassParameter<T> {
    public T f(T arg) { return arg; }
    }
  • 泛型接口

    1
    2
    3
    interface InterfaceParameter<T> {
    T f(T arg);
    }
  • 泛型方法

    1
    2
    3
    class MethodParameter {
    public static <T> T f(T arg) { return arg; }
    }
阅读全文 »
123…14
云逸云飞

云逸云飞

A Java Programmer

70 日志
8 分类
23 标签
RSS
GitHub E-Mail
© 2018 – 2019 云逸云飞