Java 线程 初识

 

说完这个线程,java部分就要结束了,就开始真正的Android路程就开始了,下一篇文章是Android的四大组件讲解。

1. 在学习线程之前需要知道的几个概念

多线程:一个进程运行时产生了多个线程,目的是为了节约CPU资源。

并发:是指能处理多个同时性活动的能力,并发事件之间不一定要同一时刻发生。

并行:同时发生两个并发事件。

线程安全:在并发的情况下,该代码经过多线程使用,线程的调度顺序不影响任何结果。

同步:Java中同步是指人为控制、保证共享资源的多线程访问成为线程安全,来保证结果准确。

 

2. 线程的状态

当一个线程完成一轮时,它移到可运行队列的尾部等待,直到它最终排队到该队列的前端,才能被再次选中。

锁是用来保护资源在并发环境下的数据安全。

做两件事情 :维护线程状态 , 阻塞或者唤起线程。

需要考虑的点:
1.竞争策略 (公平和非公平)
2.等待策略 (自旋等待或者挂起)
3.是否可重入 (持有锁的线程是否可以多次申请该锁)
4.是否可以被多个对象持有(互斥还是共享)
5.竞争者 (线程)
6.被竞争的资源 (锁 & 锁保护的数据)
7.condition

 

3. 多线程机制

monitor:解决同步问题的调度工具,每个对象都会内置这样一个监听器,用这个监听器来判断该线程继续执行还是阻塞。这个监听器只会在synchronized范围内才发挥作用,而在非多线程的情况下失效。

示例:生产者消费者模式

    //生产者
    public synchronized void producer(){

        if (product >= PRODUCT_MAX){
            try {
                wait();
                //缓冲池已满,停止生产
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return;
        }
        product++;
        Log.i(TAG,"生产者生产第"+product+"个产品");
        notifyAll();
    }



    //消费者
    public synchronized void consumer(){

        if (product <= PRODUCT_MIN){
            try {
                wait();
                //缓冲池没有产品,停止消费
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            product--;
            Log.i(TAG,"消费者消费第"+product+"个产品");
            notifyAll();
        }
    }

多线程模型:为了同时支持用户线程和内核线程,实现用户级线程和内核级线程的连接。main memory(主存)、working memory(线程栈),在处理数据时,线程会把值从主存load到本地栈,完成操作后再save回去。

多线程模型有多对一、一对一、多对多模型。

volatile:每次针对该变量的操作都激发一次load and save。

多线程使用的变量要使用volatile或者final修饰,否则,如果B线程修改了这个变量的值,A线程看到的还是B线程修改之前的值。但如果线程是安全的,加volatile会牺牲性能,因为volatile就是不去缓存。

 

4. 基本线程类

Thread、Runnable、Callable

常用的多线程设计模式有:Future、Master-Worker、Guard Susperionsion、不变、生产者-消费者 模式。

 

5. 多线程控制类

ThreadLocal类:

ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。

每个Thread都持有一个TreadLocalMap类型的变量,以本身为key,以目标为value。

主要方法是get()和set()。

 

容器类: BlockingQueue 和 ConcurrentHashMap:

是线程安全的类。阻塞队列,一般是向队尾添加新的元素,从队头取元素。

put() : 带阻塞的放元素,当队列中对象的个数大于所设置的最大值的时候,会阻塞 。
take() : 带阻塞的取元素,当队列中的对象个数等于0的时候会等待。

 

线程池(使用ThreadPoolExecutors创建):

为了解决频繁的创建线程,销毁线程,提高系统的开销。

execute()方法: 可以向线程池提交一个任务,交由线程池去执行 
submit()方法: 这个方法也是用来向线程池提交任务的,但是它和execute()方法不同,它能够返回任务执行的结果,去看submit()方法的实现,会发现它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果。 
shutdown()和shutdownNow()是用来关闭线程池的。

创建线程池应该使用 ThreadPoolExecutors,而不允许使用Executors 来构建线程池,因为FixedThreadPool 和 SingleThreadExecutor 允许的请求队列的最大长度为 Integer.MAX_VALUE, 可能会堆积大量的请求,从而导致OOM。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值