Java教程

【Java】 多线程|线程池|计时器

本文主要是介绍【Java】 多线程|线程池|计时器,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

(一)、多线程

1、线程创建方式:

(1)继承Thread类

     class PrimeThread extends Thread {
         long minPrime;
         PrimeThread(long minPrime) {
             this.minPrime = minPrime;
         }

         public void run() {
             // compute primes larger than minPrime
              . . .
         }
     }

     PrimeThread p = new PrimeThread(143);
     p.start();

编码简单,但存在单继承的局限性,不能继承其他类,不便于扩展。

重写的Run方法不能返回执行结果。

不适合需要返回执行结果的场景。

(2)实现Runnble接口

     class PrimeRun implements Runnable {
         long minPrime;
         PrimeRun(long minPrime) {
             this.minPrime = minPrime;
         }

         public void run() {
             // compute primes larger than minPrime
              . . .
         }
     }

     PrimeRun p = new PrimeRun(143);
     new Thread(p).start();

线程任务类实现接口,便于扩展,但编程多一层包装对象。

重写的Run方法不能返回执行结果。

不适合需要返回执行结果的场景。

(3)实现Callable接口

     class PrimeCallable implements Callable<V>{
         long minPrime;
         PrimeCallable (long minPrime) {
             this.minPrime = minPrime;
         }

         public V call() throws Exception{
             // compute primes larger than minPrime
              . . .
              return V;
         }
     }

     Callable<V> call = new PrimeCallable(143);
     FutureTask<V> target = new FutureTask<T>(call);
     new Thread(target ).start();       
     V result = target.get();

通过实现Callable接口再封装成FutureTask对象来创建任务对象。

线程任务类实现接口,扩展性强,可以在线程执行完毕后通过FutureTask返回执行结果。

编码更加更复杂(有点牵强)。

2、线程常用方法

(1)final String getName()  

Returns this thread's name.(获取线程名称)

(2)final void setName(String name)  

Changes the name of this thread to be equal to the argument name.(设置线程名称)

(3)static Thread currentThread()

Returns a reference to the currently executing thread object.(获取当前线程对象)

没必要为线程设置名称,默认名字即可。

3、线程安全问题

多个线程同事操作同一个共享资源的时候可能出现业务安全问题,称为线程安全问题。

线程同步实现使用加锁,把共享资源上锁,让多线程实现先后依次访问。

(1)同步代码块

synchronized(同步锁对象){操作共享资源的代码}

代码块内容被加锁,代码块执行完毕后自动解锁。

同步锁对象理论上可以是任意唯一对象,但存在每个对象创建都会受与锁对象局限。

实例方法推荐使用this作为锁对象,

静态方法推荐使用字节码(类名.call)作为锁对象。

(2)同步方法

在方法定义时使用synchronized修饰即可。

算是隐式锁对象,将整个方法作为同步代码块。

同步方法默认使用this和类名.call作为锁对象

(3)Lock锁

使用Lock的实现类ReentrantLock创建。

 class X {
   private final ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() {
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock();
     }
   }
 }

比synchronized丰富,更加强大。

4、线程通信

通常通过共享一个数据的方式实现,根据数据来决定等待自己或是唤醒别人。

如生产者与消费者模型:生产者线程负责生产数据,消费者线程负责消费生产者生产的数据。

一般要求:生产者线程生产完后唤醒消费者,等待自己,消费者消费完后,唤醒生产者,等待自己。

Object类的等待和唤醒方法:

void wait()

void notify()

void notifyall()

注意:上诉方法应该使用当前同步锁对象进行调用。

(二)、线程池

Interface ExecutorService

Class Executors

(三)、计时器

Class Timer

Interface ScheduledExecutorService

 

这篇关于【Java】 多线程|线程池|计时器的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!