`
cherryQQ
  • 浏览: 1137081 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

java 线程池 多线程

阅读更多
我看到过的好的帖子,转过来,有需要的朋友,可以参考


在新的JDK5.0中,对thread做了一些改进,我通过阅读一些资料写下了下面的总结,请大家看看。

1.创建线程
在java中实现多线程有两种方法,一个是直接继承Thread类,一个是实现Runnable接口,但是推荐的是第二种。因为在逻辑上应该要把一个线程要做的事情以及做这个事情的方法分开;对于Thread来讲,它只负责线程的操作,而具体要做的事情就应该放在Runnable中。但不管是那种方式,都要实现public void run()方法,但启动线程用start而不是run。

2.终止线程
在1.0中,可以用stop方法来终止,但是现在这种方法已经被禁用了,改用interrupt方法。interrupt方法并不是强制终止线程,它只能设置线程的interrupted状态,而在线程中一般使用一下方式:
while (!Thread.currentThread().isInterrupted() && more work to do)
{
do more work
}
而被block的线程在被调用interrupt时会产生InterruptException,此时是否终止线程由本线程自己决定。程序的一般形式是:
public void run()
{
try
{
. . .
while (!Thread.currentThread().isInterrupted() && more work to do)
{
do more work
}
}
catch(InterruptedException e)
{
// thread was interrupted during sleep or wait
}
finally
{
cleanup, if required
}
// exiting the run method terminates the thread
}

Thread.sleep方法也会产生InterruptedException,因此,如果每次在做完一些工作后调用了sleep方法,那么就不用检查isInterrupted,而是直接捕捉InterruptedException。

在捕捉到InterruptedException时,如果没有其他的事情可做,最好做一下处理,不能用{}
1)
void mySubTask()
{
. . .
try { sleep(delay); }
catch (InterruptedException e) { Thread().currentThread().interrupt(); }
. . .
}
或是
2)
void mySubTask() throws InterruptedException
{
. . .
sleep(delay);
. . .
}

3.线程状态
New:当使用new创建一个线程时
Runnable: 调用start或是从blocked状态出来时
Blocked:sleep, block on input/output, try to acquire lock, suspend, wait.
Dead: 运行完成或有exception产生。

4.线程优先级
可以设置线程优先级,但是不能保证高优先级的线程就会被先运行

5.线程组
可以把多个线程加到一个线程组里面去,这样可以对这些线程进行一些统一的操作,例如
ThreadGroup g = new ThreadGroup(groupName)
...
g.interrupt(); // interrupt all threads in group g

6.为Uncaught Exceptions设置Handlers
在java 5.0中,可以为线程中产生的unchecked exception设置一个处理器,这个处理器必须实现UncaughtExceptionHandler接口。
可以调用线程实例的setUncaughtExceptionHandler方法为每个线程设置一个处理器,也可以调用Thread.setDefaultUncaughtExceptionHandler来为所有的线程设置一个默认的处理器。如果没有给每一个线程设置处理器,那线程会首先使用线程组的处理器,如果还没有再使用默认的处理器。

7.Synchronization
多线程很重要的一个问题就是同步的问题,如果不解决好同步的问题一个是可能会引起数据的混乱,而且还有可能造成线程的死锁。在Java 5.0之前,用synchronized来解决这个问题,在5.0中加入了一个新的类:ReentrantLock

使用lock的基本形式是:
myLock.lock(); // a ReentrantLock object
try
{
critical section
}
finally
{
myLock.unlock(); // make sure the lock is unlocked even if an exception is thrown
}

这个锁被称为Reentrant的原因是在一个线程中可以重复多次申请同一个锁,系统会保留加锁的次数,而在解锁的时候也就必须执行相同次数。

在一个线程已经得到锁可以执行程序的时候,可能会发现需要的条件还不能满足,这时他就必须等待直到条件满足。但是因为它已经对所需要操作的东西加了锁,其他的线程不能访问,因此它又可能会永远等待下去。现在可以用Condition Object来避免这种情况。
sufficientFunds = bankLock.newCondition();
如果条件不满足:
sufficientFunds.await();
这时线程就会释放锁并进入blocked状态,其他线程就有机会执行操作。当其他线程执行完后,就可通知等待的线程继续执行它的操作了:
sufficientFunds.signalAll();
当然也可以调用singal方法,这样效率会高一些,但是有一定的危险性,因为它的唤醒具有随机性。

在5.0之前,采用的是synchronized关键字来进行同步,但是和lock相比它有一些局限性:
1. 申请锁的线程不能被interrupt
2. 没有timeout设置
3. 只有一个隐性的condition条件

另外,在申请锁的时候可以用tryLock方法,它会返回一个bool值来表示锁是否申请成功,如果没有成功,程序就可以做其他的事情了。

tryLock, await方法都可以被interrupt。

java.util.concurrent.locks包中提供了两种锁,一个就是ReentrantLock,另一个是ReentrantReadWriteLock,一般用于多操作远远多于写操作的时候:
private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private Lock readLock = rwl.readLock();
private Lock writeLock = rwl.writeLock();

8. Callables and Futures
实现多线程时一般用的是Runnable接口,但是他有一个问题就是他没有参数和返回值,所以当执行一个线程需要返回一个值的时候就不是很方便了。Callable接口和Runnable差不多,但是他提供了参数和返回值:
public interface Callable<V>
{
V call() throws Exception;
}
而Future接口可以保留异步执行的值:
public interface Future<V>
{
V get() throws . . .;
V get(long timeout, TimeUnit unit) throws . . .;
void cancel(boolean mayInterrupt);
boolean isCancelled();
boolean isDone();
}

FutureTask可以很方便的把Callable转换成Future和Runnable:
Callable<Integer> myComputation = . . .;
FutureTask<Integer> task = new FutureTask<Integer>(myComputation);
Thread t = new Thread(task); // it's a Runnable
t.start();
. . .
Integer result = task.get(); // it's a Future

9.用Executors创建线程池
用线程池有两个好处:1. 减少创建线程的开销。2. 控制线程的数量。
EXecutors提供了一些方法可以很方便的创建线程池:
newCachedThreadPool
New threads are created as needed; idle threads are kept for 60 seconds.

newFixedThreadPool
The pool contains a fixed set of threads; idle threads are kept indefinitely.

newSingleThreadExecutor
A "pool" with a single thread that executes the submitted tasks sequentially.

newScheduledThreadPool
A fixed-thread pool for scheduled execution.

newSingleThreadScheduledExecutor
A single-thread "pool" for scheduled execution.

在使用Executors时,先调用这些静态方法创建线程池,得到一个ExecutorService对象,然后用这个对象的submit方法提交你的Runnable或是Callable对象。
Future<?> submit(Runnable task)
Future<T> submit(Runnable task, T result)
Future<T> submit(Callable<T> task)
如果不再需要任何提交,就用shutdown方法来关闭线程池。

10.在界面中使用多线程
对于GUI设计来说,很重要的一个原则就是要及时的给用户反馈,就算是不能立即得到结果,界面也不能停在那里,是用户不知道发生了什么事情,必须让用户随时知道程序在坐什么。所以当程序要执行一段需要消耗比较长时间的操作时,就要使用多线程。

但是,有些界面控件并不是线程安全的,在使用这些控件时就要特别注意。在API doc中这些都有注明,使用的时候就可以查一下。

如果想在自己另外所创建的线程执行过程中随时更新界面来表示执行进程,要注意的一点是,这个线程并不能直接调用界面控件的方法,而要采用EventQueue类的invokeLater,invokeAndWait方法:
EventQueue.invokeLater(new
Runnable()
{
public void run()
{
label.setText(percentage + "% complete");
}
});

分享到:
评论

相关推荐

    Java多线程Executors批量执行数据实现限流

    java线程池Executors实现数据批量操作。 批量异步Executors处理数据,实现限流操作,QPS限流。 线程池调用第三方接口限流实现逻辑。 案例适合: 1.批量处理大数据。 2.数据批量导出。 3任务数据异步执行。 4.多线程...

    JAVA使用线程池查询大批量数据

    线程池是一种多线程处理形式,预先创建了若干个线程,当有任务需要执行时,会从线程池中取出一个线程来执行任务,任务执行完毕后,线程返回线程池中等待新的任务。这种机制避免了频繁创建和销毁线程带来的性能开销,...

    java多线程查询数据库

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

    java线程池完整代码

    Java 线程池是 Java 语言中的一个重要概念,它允许开发者创建和管理多个线程,以提高程序的并发性和性能。下面是对给定文件的解析,包括 title、description、标签和部分内容的解析。 标题解析 标题 "Java 线程池...

    java线程池使用后到底要关闭吗

    因为线程池中仍然有很多线程在运行,占用系统资源,导致内存泄露和应用崩溃。 通过实例代码,我们可以看到,如果不关闭线程池,可能会导致内存泄露和应用崩溃。在代码中,我们创建了一个线程池,然后执行一个打印...

    java多线程分页查询

    ### Java多线程分页查询知识点详解 #### 一、背景与需求分析 在实际的软件开发过程中,尤其是在处理大量数据时,如何高效地进行数据查询成为了一个关键问题。例如,在一个用户众多的社交平台上,当用户需要查看...

    Java线程池及观察者模式解决多线程意外死亡重启问题

    Java线程池是Java并发编程中的重要组成部分,它...总之,通过Java线程池和观察者模式的结合,我们可以构建一个健壮的多线程系统,即使在部分线程意外终止的情况下,也能及时发现并采取措施恢复,确保系统的稳定运行。

    java简单分布式架构,多个数据源,线程池多线程访问

    本项目围绕“Java简单分布式架构,多个数据源,线程池多线程访问”这一主题展开,旨在通过利用Java技术栈实现一个高效的分布式系统。 首先,我们关注的是“分布式”这一概念。分布式系统是由多台计算机通过网络连接...

    一个通用的Java线程池类

    目标:Java中多线程技术是一个难点,但是也是一个核心技术。因为Java本身就是一个多线程语言。本人目前在给46班讲授Swing的网络编程--使用Swing来模拟真实的QQ实时聊天软件。因为涉及到Socket编程,所以一定会使用多...

    java线程池封装j

    Java线程池是一种高效管理线程的技术,它允许开发者预定义一组线程,根据任务的需要灵活调度,而不是每次需要执行任务时都创建新的线程。这种设计模式大大提高了系统的性能,减少了系统资源的消耗,特别是在高并发...

    Java 线程池的原理与实现

    Java线程池是一种高级的多线程处理框架,它是Java并发编程中非常重要的一个组件。线程池的原理和实现涉及到操作系统调度、内存管理和并发控制等多个方面。理解线程池的工作原理有助于优化程序性能,避免过度创建和...

    Java 利用多线程实现文件的分片下载

    刚学完多线程和线程池,以及线程爱好者。 使用场景及目标: 大文件的快速下载,经测试在100M带宽的网络下,下载一个40M的文件,不超过两秒钟,当然还得根据自己电脑的配置来讲。 其他说明: 文件如果特别小,而...

    curl线程池多线程调用

    标题"curl线程池多线程调用"指向的关键技术点包括: 1. **多线程**:多线程是一种并发执行任务的方法,通过创建多个线程,可以同时处理多个网络请求,从而提高整体的执行效率。在`curl`中,可以通过并行运行多个`...

    java线程池实例详细讲解

    总之,Java线程池是实现多线程并行处理的关键工具,理解和熟练使用它可以显著提高程序的并发性能,降低系统的资源消耗。通过深入学习和实践,我们可以更好地利用线程池来优化我们的Java应用程序。

    线程池管理多线程上传

    线程池管理和多线程上传是并发编程中的一个重要实践,特别是在大数据传输和网络服务中。在Java等编程语言中,线程池通过有效地管理和复用线程资源,避免了频繁创建和销毁线程带来的开销,提升了系统性能。下面将详细...

    Java多线程批量数据导入的方法详解

    Java多线程批量数据导入的方法详解 在数据处理中,遇到大量数据导入时,为了提高处理的速度,可以选择使用多线程来批量处理这些处理。常见的场景有大文件导入数据库、数据同步等。在这些场景中,数据导入的过程可以...

    java多线程实现大批量数据导入源码

    总的来说,本项目通过Java多线程技术,结合合理的数据切分和线程池管理,实现对大数据的高效批量处理。通过分析和优化这些关键点,我们可以根据实际情况调整参数,进一步提高数据导入导出的效率。

    Java线程池文档

    总之,Java线程池是Java多线程编程中不可或缺的一部分,通过合理的线程池配置,可以显著提升程序的并发性能和资源利用率。在理解和使用线程池时,不仅要关注其实现原理,还需要根据实际需求调整线程池的配置,以达到...

    java多线程加队列上传文件_后台处理

    ### Java多线程加队列上传文件_后台处理 #### 概述 本文将详细介绍一个基于Java实现的多线程文件上传系统,并结合队列管理技术来优化后台处理流程。该系统通过创建多个线程来并行处理客户端的文件上传请求,同时...

    基于Java线程池技术的数据爬虫设计与实现.pdf

    本文所提及的基于Java线程池技术的数据爬虫设计与实现,不仅涉及到了数据爬虫的原理和架构,还包括了多线程编程的知识点,以及线程池技术在数据爬虫中的具体应用。 首先,数据爬虫的基本原理是模拟用户的点击行为,...

Global site tag (gtag.js) - Google Analytics