0
点赞
收藏
分享

微信扫一扫

JAVA--JUC

胡桑_b06e 2024-11-06 阅读 14

Callable接口:

实现Thread的方法:

1.继承Thread

2.实现Runnable

3.基于lambda

4.基于Callable

5.基于线程池

Runnable和Callable区别:

Runnable关注过程,不关注结果,Runnable提供的run方法返回值为void。

Callable则关注结果,提供的call方法,返回值是就是线程执行任务得到的结果。

但是Callable不可以直接传入Thread,需要一个FutureTask来实现转换。.

下面是一个使用Callable接口来实现从1加到100的计算

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Thread00 {
    public static void main(String[]args) throws InterruptedException, ExecutionException {
        Callable<Integer> callable = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
              int result = 0;
                for (int i = 0; i <= 100 ; i++) {
                    result += i;
                }
                return result;
            }
        };
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        Thread t = new Thread(futureTask);
        t.start();
        System.out.println(futureTask.get());
    }
}

ReentrantLock:

        ReentrantLock也就是可重入锁,在早期Java中,synchronized不够强大时,用来实现可重入锁的(现在synchronized已经实现可重入锁的功能了)

       这个对象提供了两种方法:lock,unlock。

但是这种写法容易引起加锁后忘记解锁,或者在unlock之前触发了return或者异常,也会导致unlock执行不到。需要把unlock操作放入finally中。

ReentrantLock现在存在的意义:

1.ReentrantLock提供了tryLock操作。     

lock直接进行加锁,如果加锁失败,就会阻塞。trylock,尝试进行加锁,如果加锁失败,不阻塞,直接返回false。

2.ReentrantLock提供了公平锁的实现,

在ReentrantLock的构造方法中填写对应参数,就可以设置为公平锁。

3.搭配的等待通知机制不同于synchronized。

synchronized搭配wait/notify。

ReentrantLock搭配Condition类,功能比wait/notify强一点。

信号量Semaphore

锁本质上也是一种特殊的信号量,计数值为1的二元信号量。释放状态为1,加锁状态为0 。

以下就是提供创建一个Semaphore来模拟线程加锁的例子

import java.util.concurrent.Semaphore;

public class Thread02 {
    private static int count = 0;
    public static void main(String[]args) throws InterruptedException {
        Semaphore semaphore = new Semaphore(1);
        Thread t1 = new Thread(()->{
            for (int i = 0; i <= 100; i++) {
                try {
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                count+=i;
                semaphore.release();
            }
        });
        Thread t2 = new Thread(()->{
            for (int i = 0; i <= 100 ; i++) {
                try {
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                count+=i;
                semaphore.release();
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(count);
    }
}

CountDownLatch

针对特定场景解决问题的小工具

比如:多线程执行一个任务,把大的任务拆成几个部分,由每个线程分别执行。比如多线程下载。

像多线程下载的场景,最终执行完成后,要把所有内容拼到一起,而要拼到一起,就要等到所有线程执行完毕,使用CountDownLatch就可以很方便的感知到这个事情,比多次使用join要方便很多。

以下是模拟多线程下载的代码

import java.util.Random;
import java.util.concurrent.CountDownLatch;

public class Thread03 {
    public static void main(String[]args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(10);
        for (int i = 0; i < 10; i++) {
            int id = i;
            Thread t = new Thread(()->{
                Random random = new Random();
                int time = (random.nextInt(5)+1)*1000;
                System.out.println("线程 "+id+"开始执行");
                try {
                    Thread.sleep(time);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("第"+id+"个任务执行完毕");
                latch.countDown();//告知 CountDownLatch 该线程已执行完毕
            });
            t.start();
        }
        latch.await();//阻塞,直到所有任务结束
        System.out.println("所有任务都已经执行完毕");
    }
}

线程安全的集合类

Vector,Stack,Hashtable,他们把关键方法加上了synchronized,但是他们在单线程时也加上了锁,会造成资源浪费,所以官方不建议使用了。

CopyOnWriteArrayList:写时拷贝。如果多个线程读这个集合时是没问题的,但是如果有线程想要修改这里的值时,它就会将顺序表复制一份,修改新的顺序表内容,并且修改引用的指向。但是也有局限性:修改不能太频繁;顺序表不能太大。

多线程使用队列

1.自己加锁。

2.BlockingQueue

多线程使用哈希表

Hashtable:在关键方法上添加了synchnorized。在此基础上,标准库引入了更好的ConcurrentHashMap

ConcurrentHashMap:1.缩小了锁的粒度。2.充分的使用了CAS原子操作,减少了加锁。3.针对扩容操作的优化。

举报

相关推荐

0 条评论