single thread execution线程设计模式学习

本文深入探讨了单线程执行模式(singlethreadexecution),解释了其概念与实现方式,重点在于如何使用synchronized关键字来保护共享资源,避免多线程环境下的死锁问题,并通过Java代码示例展示了如何利用Semaphore控制资源的并发访问。

概念
       single thread execution 即“以一个线程执行”。就像独木桥同一时间只允许一个人通行一样,该模式主要用于限制,以确保同一时间内只能让一个线程执行处理。
实现
       主要使用synchronized关键字实现。
角色(使用的对象)
SharedResource(共享资源)
使用synchronized对方法或者代码块使用以保护共享资源
死锁
在该模式下发生死锁的条件:

  • 存在多个ShareResource 角色
  • 线程在持有某个ShareResource 角色锁的同时,还想获得其他ShareResource角色的锁
  • 获取ShareResource角色的锁的顺序并不是固定的(ShareResource角色是对称的)

笔记

  • 对于多线程来说,继承会引起一些麻烦的问题,通常称之为继承反常。
  • 该模式会降低程序性能(1..获取锁会花费时间2线程冲突引起的等待)
  • java编程规范定义了一些原子操作。eg:char,int等基本类型(primitive type)的赋值和引用操作都是原子的,对象等引用类型(reference type)的赋值和引用也是原子的。但是,也有例外,Java编程规范规定,long、double的复制和引用操作不是原子的。(实际上大部分Java虚拟机也都将long和double的操作实现为了原子)
  • 对字段加上volatile关键字,对该字段的操作就是原子的了

延伸
java.util.concurrent包和计数信号量
资源的许可数将通过Semaphore的构造函数来指定
Semaphore的acquire用于确保有可用资源,release方法用于释放资源

package singleThreadExecution;

import java.util.Random;
import java.util.concurrent.Semaphore;

public class BoundResource {
    private final Semaphore semaphore;
    private final int permits;
    private final static Random random = new Random(314159);

    public BoundResource(int permits) {
        this.semaphore = new Semaphore(permits);
        this.permits = permits;
    }

    public void use() throws InterruptedException {
        semaphore.acquire(); //判断是否有资源可用,不可用等待
        try {
            doUse();
        }finally {
            semaphore.release();   //释放资源
        }
    }

    /**
     * 实际使用资源
     * @throws InterruptedException
     */
    protected void doUse() throws InterruptedException {
        Log.println("BEGIN: used = " + (permits - semaphore.availablePermits()));
        Thread.sleep(random.nextInt(500));
        Log.println("END:   used = " + (permits - semaphore.availablePermits()));
    }
}

package singleThreadExecution;

public class Log {
    public static void println(String s){
        System.out.println(Thread.currentThread().getName() + ":" + s);
    }
}

package singleThreadExecution;

public class Main {
    public static void main(String[] args) {
        BoundResource boundResource = new BoundResource(3);
        for (int i=0;i<10;i++){
            new UserThead(boundResource).start();
        }
    }
}

package singleThreadExecution;

import java.util.Random;

public class UserThead extends Thread {
    private final static Random random = new Random(26535);
    private final BoundResource boundResource;

    public UserThead(BoundResource boundResource){
        this.boundResource = boundResource;
    }

    @Override
    public void run() {
        while (true){
            try {
                boundResource.use();
                Thread.sleep(random.nextInt(3000));
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

结果

Thread-0:BEGIN: used = 1
Thread-1:BEGIN: used = 2
Thread-2:BEGIN: used = 3
Thread-1:END:   used = 3
Thread-3:BEGIN: used = 3
Thread-3:END:   used = 3
Thread-4:BEGIN: used = 3
Thread-2:END:   used = 3
Thread-5:BEGIN: used = 3
Thread-4:END:   used = 3
Thread-6:BEGIN: used = 3
Thread-6:END:   used = 3
Thread-7:BEGIN: used = 3
Thread-0:END:   used = 3
Thread-8:BEGIN: used = 3
Thread-5:END:   used = 3
Thread-9:BEGIN: used = 3
Thread-8:END:   used = 3
Thread-9:END:   used = 2
Thread-1:BEGIN: used = 2
Thread-7:END:   used = 2
Thread-8:BEGIN: used = 2
Thread-3:BEGIN: used = 3
Thread-1:END:   used = 3
Thread-4:BEGIN: used = 3
Thread-8:END:   used = 3
Thread-3:END:   used = 2
Thread-4:END:   used = 1
Thread-7:BEGIN: used = 1
Thread-7:END:   used = 1
Thread-4:BEGIN: used = 1
Thread-4:END:   used = 1
Thread-5:BEGIN: used = 1
Thread-1:BEGIN: used = 2
Thread-1:END:   used = 2
Thread-4:BEGIN: used = 2
Thread-5:END:   used = 2
Thread-2:BEGIN: used = 2
Thread-9:BEGIN: used = 3
Thread-4:END:   used = 3
Thread-0:BEGIN: used = 3
Thread-2:END:   used = 3
Thread-0:END:   used = 2
Thread-3:BEGIN: used = 2
Thread-8:BEGIN: used = 3
Thread-9:END:   used = 3
Thread-6:BEGIN: used = 3
Thread-6:END:   used = 3
Thread-1:BEGIN: used = 3
Thread-8:END:   used = 3
Thread-9:BEGIN: used = 3
Thread-3:END:   used = 3
Thread-4:BEGIN: used = 3
Thread-1:END:   used = 3
Thread-4:END:   used = 2
Thread-8:BEGIN: used = 2
Thread-0:BEGIN: used = 3
Thread-9:END:   used = 3
Thread-9:BEGIN: used = 3
Thread-8:END:   used = 3
Thread-9:END:   used = 2
Thread-7:BEGIN: used = 2
Thread-0:END:   used = 2
Thread-5:BEGIN: used = 2
Thread-6:BEGIN: used = 3
Thread-6:END:   used = 3
Thread-7:END:   used = 2
Thread-5:END:   used = 1
Thread-3:BEGIN: used = 1
Thread-3:END:   used = 1
Thread-0:BEGIN: used = 1
Thread-7:BEGIN: used = 2
Thread-8:BEGIN: used = 3
Thread-0:END:   used = 3
Thread-2:BEGIN: used = 3
Thread-8:END:   used = 3
Thread-2:END:   used = 2
Thread-7:END:   used = 1
Thread-0:BEGIN: used = 1
Thread-7:BEGIN: used = 2
Thread-4:BEGIN: used = 3
Thread-7:END:   used = 3
Thread-0:END:   used = 2
Thread-4:END:   used = 1
Thread-2:BEGIN: used = 1
Thread-1:BEGIN: used = 2
Thread-1:END:   used = 2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值