Java / Android 多线程和 synchroized 锁

s

AsyncTask 在Android R中标注了废弃 

synchronized 同步

Thread:

thread.start()

 public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

    private native void start0();

start0 是个native方法

进程和线程 进程> 线程

进程= 操作系统独立区域 ,可以有多条线程

进程和线程可以进行并行工作,线程依赖进程

Runable: 接口 重写run

new Thread(runnable)

thread.start(runnable)  runnable在Thread内部标为target

相比于thread,runnable可以重用 : Thread1(runnable),Thread2(runnable)

ThreadFactory: Thread 工厂方法
  private static void threadFactory() {
        AtomicInteger count = new AtomicInteger(0);
        ThreadFactory factory = new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r,"Thread-"+count.incrementAndGet());
            }
        };
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        };

        Thread thread = factory.newThread(runnable);
        thread.start();

        Thread thread1 = factory.newThread(runnable);
        thread1.start();
    }

Executor: 接口

   private static void executor() {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("runnable run");
            }
        };
        Executor executor = Executors.newCachedThreadPool();
        executor.execute(runnable);
        executor.execute(runnable);
        executor.execute(runnable);
    }
public interface Executor {

    /**
     * Executes the given command at some time in the future.  The command
     * may execute in a new thread, in a pooled thread, or in the calling
     * thread, at the discretion of the {@code Executor} implementation.
     *
     * @param command the runnable task
     * @throws RejectedExecutionException if this task cannot be
     * accepted for execution
     * @throws NullPointerException if command is null
     */
    void execute(Runnable command);
}

newCachedThreadPool 返回 ExecutorService

void shutdown(); //关闭任务
List<Runnable> shutdownNow();//立即关闭 但是会调用intrat 用这个是安全的

  public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

内部创建线程池,和连接池一样. 包含了线程的创建 销毁等操作 (0 //默认大小,当超过最大值Integer.MAX_VALUE,就会销毁到默认大小)

60L, TimeUnit.SECONDS,线程等待回收时间
 new SynchronousQueue<Runnable>() 创建队列

Executor executor1 = Executors.newSingleThreadExecutor();创建1个线程
   public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
  public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

newFixedThreadPool 创建固定数量的线程,不推荐,如果用得少或者不用也会是这么多,而且不可扩展更多,用来处理多个集中任务

newScheduledThreadPool:可以添加延迟
  public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
Callable:有返回值的Runnable ,方法 call : Type

  private static void callable() {
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "666";
            }
        };
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<String> future = executorService.submit(callable); //后台任务Future 否则就会阻塞主线程  execure则会阻塞进行等待
        try {
            String result = future.get(); //阻塞进行取值,
            System.out.println(result);
        } catch (ExecutionException | InterruptedException e) {
            throw new RuntimeException(e);
        }

    }

  if (future.isDone()){
            //如果完成任务
        }

流程图

线程同步:

public class SynchronizedDemo1 implements TestDemo{
    private boolean running =true;
    private void stop(){
        running = false;
    }

    @Override
    public void runTest() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                int round = 1;
                while (running){

                }
            }
        }).start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        stop();
    }
}

看出会等待1秒然后跳出循环,但是实际上会一直执行 

每个线程都有一块独立的区域,会把变量copy,然后改变值,然后再传回去

但是如果是多线程,copy同一个值,进行修改,数据会乱

可以使用 volatile ,改变其内存可见性,同步

多线程中如若用

x++; 则会进行两步 1 int temp = x+1, 2  x = temp 不是原子操作

需要使用 synchronized 有线程调用则其他线程等待

private synchronized void count(){
    x++; 
}

AtomicInteger = int 的包装 增加原子性和同步性

AtomicInteger count = new AtomicInteger(0); //int
   AtomicInteger count = new AtomicInteger(0); //int
        ThreadFactory factory = new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r,"Thread-"+count.incrementAndGet()); //++count
               // count.getAndIncrement() //count++
            }
        };
AtomicBoolean
    private AtomicBoolean running = new AtomicBoolean(true);
         running.set(false);
            running.get()

除此之外还有

//同一个类如果有多个synchronized 一般就是有一个监视器 monitor 进行控制,只能由一个线程调用

可以再方法内部加上

synchronized (this){用当前监视器

}

synchronized在方法上会同步锁多个方法,仅供当前线程调用

public class SynchronizedDemo3 implements TestDemo{

    private int x= 0;
    private int y = 0;
    private String name;
    private Object monitor1 = new Object();
    private Object monitor2 = new Object();
    private synchronized void count(int newValue){
       synchronized (monitor1){
           x = newValue;
           y = newValue;
       }
    }

    private void  minus(int delta){
        synchronized (monitor1){
            x -= delta;
            y -= delta;
        }

    }

    //synchronized 锁住当前方法
    private synchronized void setName(String name){
        synchronized (monitor2){
            this.name = name;
        }

    }


    @Override
    public void runTest() {

    }
}

synchronized 在方法上等同于在内部的 synchronized (this)

synchronized 作用 = 同步性,互斥

死锁:多线程中,当前线程持有的锁,但拿不到需要进行执行代码中的锁,会一直等待

乐观锁 写入时先读取, 悲观锁 -读之前加锁,写入前加锁, 主要用于数据库

static 修饰的方法 用synchronized在方法上 等同于 在方法内部( synchronized (name.class))

用当前类当做锁

单例模式双重检查锁 写法1

ReentrantLock 可重入锁 需要手动加解锁,同时也要注意是否能够正常解锁

可以使用读写锁

 private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    Lock readLock = lock.readLock();
    Lock writeLock = lock.writeLock();

线程安全本质是多个线程访问共同资源,在写入时,其他线程干预了,导致数据错误

锁机制是:对资源进行访问的一种限制

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/126301.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

雅创电子-301099 三季报分析(20231109)

雅创电子-301099 基本情况 公司名称&#xff1a;上海雅创电子集团股份有限公司 A股简称&#xff1a;雅创电子 成立日期&#xff1a;2008-01-14 上市日期&#xff1a;2021-11-22 所属行业&#xff1a;批发业 周期性&#xff1a;0 主营业务&#xff1a;分销东芝、首尔半导体、村田…

golang工程中间件——redis常用结构及应用(set,zset)

Redis 命令中心 这些篇文章专门以应用为主&#xff0c;原理性的后续博主复习到的时候再详细阐述 set 集合&#xff0c;为了描述它的特征&#xff0c;我们可称呼为无序集合&#xff1b;集合的特征是唯一&#xff0c;集合中的元素是唯一存在 的&#xff1b; 存储结构 元素都…

前端构建工具vite与webpack详解

文章目录 前言什么是构建工具先说说企业级项目里都需要具备哪些功能&#xff1f;这是代码改动后需要做的事情样例总结 一、构建工具他到底承担了哪些脏活累活&#xff1f;二、vite相较于webpack的优势三、 vite会不会取代webpack四、 你必须要理解的vite脚手架和vitecreate-vit…

Pytorch卷积神经网络各层介绍与实现

本文将讲解&#xff0c;PyTorch卷积神经网络各层实现与介绍&#xff0c;包括&#xff1a;基本骨架–nn.Module的使用、卷积操作、卷积层、池化层、激活函数、全连接层的介绍。 &#x1f61c; 对于相关原理&#xff0c;可以跳转&#x1f449;卷积神经网络CNN各层基本知识 &…

Nginx缓存基础

1 nginx缓存的流程 客户端需要访问服务器的数据时&#xff0c;如果都直接向服务器发送请求&#xff0c;服务器接收过多的请求&#xff0c;压力会比较大&#xff0c;也比较耗时&#xff1b;而如果在nginx缓存一定的数据&#xff0c;使客户端向基于nginx的代理服务器发送请求&…

FRC-EP系列--你的汽车数据一站式管家

FRC-EP系列产品主要面向汽车动力总成测试的客户&#xff0c;主要应用方向为残余总线仿真及网关。本文将详细介绍FRC-EP的产品特性和应用场景。 应用场景&#xff1a; 汽车电子生成研发过程中&#xff0c;需要对汽车各个控制器进行仿真测试&#xff0c;典型的测试对象有&#…

原语:串并转换器

串并转换器OSERDESE2 可被Select IO IP核调用。 OSERDESE2允许DDR功能 参考&#xff1a; FPGA原语学习与整理第二弹&#xff0c;OSERDESE2串并转换器 - 知乎 (zhihu.com) 正点原子。 ISERDESE2原语和OSERDESE2原语是串并转换器&#xff0c;他的的功能都是实现串行数据和并行…

基于安卓android微信小程序的物流仓储系统

项目介绍 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术和mysql数据库来完成对系统的设计。整个开发过程首先对物流仓储系统进行需求分析&#xff0c;得出物流仓储系统主要功能。接着对物流仓储系统进行总体设计和详细…

Halcon的相机内参外参的标定

halcon标定相机内参只能使用方向标定板和圆点标定板。并且方向标定板可也可用性极高。 1.打开halcon的标定助手&#xff0c;选择标定板的描述文件&#xff0c;填写标定板的厚度&#xff0c;根据相机选择像元的尺寸和镜头的焦距。如果已有相机内参&#xff0c;只标定外参&#…

Project#2: Extendible Hash Index

文章目录 准备Task #1-Read/Write Page GuardsBasicPageGuard/ReadPageGuard/WritePageGuardUpgradeWrappersTests Task #2-Extendible Hash Table PagesHash Table Header Pages**成员变量&#xff1a;****方法实现&#xff1a;** Hash Table Directory Pages**成员变量&#…

什么是Node.js的NVM(Node Version Manager)?它的作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

【ZYNQ】裸机 PS + PL 双网口实现之 SDK 程序设计

涉及 lwip 库文件及 ZYNQ 配置相关可参考以下文章&#xff1a; 【ZYNQ】裸机 PS PL 双网口实现之 LWIP 库文件修改 【ZYNQ】裸机 PS PL 双网口实现之 ZYNQ 配置 工程配置 启动 SDK &#xff0c;创建模板工程&#xff0c;配置 BSP。 勾选 lwip141 库。 对 lwip 做如下配置…

Elastic Observability 8.11:ES|QL、APM 中的通用分析和增强的 SLOs

作者&#xff1a;Tom Grabowski, Katrin Freihofner, Israel Ogbole Elastic Observability 8.11 引入了 ES|QL for Observability&#xff08;技术预览版&#xff09;、Universal ProfilingTM 和 Elastic APM 集成&#xff0c;以及针对 Elastic Observability 的新 SLO &#…

GD32单片机远程升级下载,手机在线升级下载程序,GD32在线固件下载升级,手机下载程序固件方法

GD32、STM32单片机&#xff0c;是我们最常见的一种MCU。通常我们在使用STM32单片机都会遇到程序在线升级下载的问题。 GD32/STM32单片机的在线下载通常需要以下几种方式完成&#xff1a; 1、使用ST/GD提供的串口下载工具&#xff0c;本地完成固件的升级下载。 2、自行完成系统B…

Ubuntu22.04配置Go环境

Ubuntu上配置Go环境biCentOS简单多了&#xff0c;有两种方案&#xff0c;一种直接使用apt进行安装&#xff0c;一种自己从官网下载安装包进行安装。 1、使用apt直接安装 更新apt安装包&#xff0c;常规操作 apt update 然后看看apt自带的Go版本是多少 apt list golang 是1…

数据结构——二叉树(2)

接上一篇文章http://t.csdnimg.cn/nsKsW&#xff0c;本次我们接着讲解关于二叉树的相关知识。 一、二叉树的相关性质&#xff1a; 1. 若规定根节点的层数为 1 &#xff0c;则一棵非空二叉树的 第 i 层上最多有 2^(i-1) 个结点. 2. 若规定根节点的层数为 1 &#xff0c;则 深度…

【QT】QT自定义C++类

在使用Qt的ui设计时&#xff0c;Qt为我们提供了标准的类&#xff0c;但是在很多复杂工程中&#xff0c;标准的类并不能满足所有的需求&#xff0c;这时就需要我们自定义C类。 下面以自定义的QPushButton作一个很简单的例子。 先新建默认Qt Widgets Application项目 一、自定义…

LabVIEW如何才能得到共享变量的引用

LabVIEW如何才能得到共享变量的引用 有一个LabVIEW 库文件 (.lvlib) &#xff0c;其中有一些定义好的共享变量。但需要得到每个共享变量的引用以便在程序运行时访问其属性。 共享变量的属性定义在“变量”类属性节点中。为了访问变量类&#xff0c;共享变量的引用必须连接到变…

Leetcode543. 二叉树的直径

Every day a Leetcode 题目来源&#xff1a;543. 二叉树的直径 解法1&#xff1a;深度优先搜索 首先我们知道一条路径的长度为该路径经过的节点数减 1&#xff0c;所以求直径&#xff08;即求路径长度的最大值&#xff09;等效于求路径经过节点数的最大值减 1。 而任意一条…

linux系统,确认账户密码正确

linux系统&#xff0c;确认账户密码正确 1、问题背景2、解决方法 1、问题背景 有时在linux系统安装软件时&#xff0c;有的软件可能会在安装过程中创建系统用户&#xff0c;同时会给出这个用户的密码。过了一段时间我们不确定这个密码是否还正确&#xff0c;那怎么确认这个密码…