线程

Android两种常见错误(ANR和FC)解决办法

牧云@^-^@ 提交于 2020-03-01 10:10:52
ANR(Activity Not Respone)(无响应) 先介绍下Main线程(也称为UI线程、主线程) 功能: 1.创建UI控件 2.更新UI控件状态 3.事件处理 限制:Main线程不建议有超过5秒的事件 出现条件: 当用户输入事件5s内没有得到响应,将弹出ANR对话框 广播接收者的onReceive()执行时间超过10s 解决方案(原则): 所有可能的耗时操作都要在子线程()中执行 常见耗时操作: I/O:网络操作 SDcard 数据运算 FC(Force close) 原因: 1.Error OOM(out of memory error) StackOverFlowError 2.RuntimeException 解决办法: 看日志 子线程不能更新UI的解决思路: 1、 将子线程执行结果发送到Main线程:handler+massage线程间通讯 发送消息: Message msg = mHandler .obtainMessage( UPLOAD , json ); mHandler .sendMessage( msg ); 接收消息: public void handleMessage(Message msg ) { switch ( msg . what ) { case UPLOAD : mTextView2 .setText((String) msg .

NO.2 Android 线程间交互

社会主义新天地 提交于 2020-03-01 10:05:14
NO.2 Android 线程间交互 零蚀 线程的终止 一个线程终止另一个线程 Thread thread = new Thread ( new Runnable ( ) { @Override public void run ( ) { } } ) ; thread . start ( ) ; thread . stop ( ) ; 线程里 有一个非常有效的终止线程的方法,可以使用stop来有效的结束一个线程,但是这个api在4.1的时候就已经被弃用了,因为结果是不可预期的,当结束线程时候,不能了解到线程所做的工作是什么,所以对这种不可控的因素,是不可靠的。 Thread thread = new Thread ( ) { @Override public void run ( ) { //重置interrupt的状态 if ( Thread . interrupted ( ) ) { // 收尾 return ; } // 下面的方法不会改变interrupt标记的状态 //if(isInterrupted()){ // return; //} } } ; thread . start ( ) ; thread . interrupt ( ) ; interrupt方法并非像stop即死,它是给这个线程做个中断标记。通知线程将被中断。如果线程在合适的位置进行终止,如上述代码。

[JavaEE] NIO与IO的区别

ε祈祈猫儿з 提交于 2020-03-01 09:52:31
nio是new io的简称,从jdk1.4就被引入了。现在的jdk已经到了1.6了,可以说不是什么新东西了。但其中的一些思想值得我来研究。这两天,我研究了下其中的套接字部分,有一些心得,在此分享。 首先先分析下:为什么要nio套接字? nio的主要作用就是用来解决速度差异的。举个例子:计算机处理的速度,和用户按键盘的速度。这两者的速度相差悬殊。如果按照经典的方法:一个用户设定一 个线程,专门等待用户的输入,无形中就造成了严重的资源浪费:每一个线程都需要珍贵的cpu时间片,由于速度差异造成了在这个交互线程中的cpu都用来等 待。 nio套接字是怎么做到的? 其实,其中的思想很简单:轮询。一个线程轮询多个input;传统的方式是:有n个客户端就要有n个服务线程+一个监听线程,现在采取这种凡是,可以仅仅使用1个线程来代替n个服务线程以此来解决。 具体应用例子: 在ftp的控制连接中,因为只有少量的字符命令进行传输,所以可以考虑利用这种轮询的方式实现,以节省资源。 ----------------------------------------------------- Java中的阻塞和非阻塞IO包各自的优劣思考 NIO 设计背后的基石:反应器模式,用于事件多路分离和分派的体系结构模式。 反应器(Reactor):用于事件多路分离和分派的体系结构模式 通常的

Java自学-多线程 交互

孤人 提交于 2020-03-01 09:41:01
Java 线程之间的交互 wait和notify 线程之间有 交互通知 的需求,考虑如下情况: 有两个线程,处理同一个英雄。 一个加血,一个减血。 减血的线程,发现血量=1,就停止减血,直到加血的线程为英雄加了血,才可以继续减血 步骤 1 : 不好的解决方式 故意设计减血线程频率更高,盖伦的血量迟早会到达1 减血线程中 使用while循环判断是否是1 ,如果是1就不停的循环,直到加血线程回复了血量 这是不好的解决方式,因为会大量占用CPU,拖慢性能 package charactor; public class Hero{ public String name; public float hp; public int damage; public synchronized void recover(){ hp=hp+1; } public synchronized void hurt(){ hp=hp-1; } public void attackHero(Hero h) { h.hp-=damage; System.out.format("%s 正在攻击 %s, %s的血变成了 %.0f%n",name,h.name,h.name,h.hp); if(h.isDead()) System.out.println(h.name +"死了!"); } public boolean

用Java模拟一个死锁

我的未来我决定 提交于 2020-03-01 08:38:36
模拟一个死锁:一个线程1在锁定A的过程中,需要锁定B,另一个线程2在锁定B的过程中需要锁定A,线程1想申请B 的锁已经被线程2锁定了,线程2 想申请A的锁,已经被线程1 锁定了,两个线程都无法执行,构成死锁。 public class T(){ public static String resource1="resource1"; public static String resource2="resource2"; public static void main(String[] args){ new Thread(new ClassA()).start(); new Thread(new ClassB()).start(); } } public class ClassA() implements Runnable{ public void run(){ synchronized(T.resource1){ System.out.println("得到resource1的 lock") Thread.sleep(3000); //下面请求resource2的锁 synchronized(T.resource2){ System.out.println("得到resource2 的lock") } } } } public class ClassB() implements

Windows线程+进程通信

丶灬走出姿态 提交于 2020-03-01 08:15:48
一 Windows线程进程 1)定义 按照MS的定义, Windows中的进程简单地说就是一个内存中的可执行程序, 提供程序运行的各种资源. 进程拥有虚拟的地址空间, 可执行代码, 数据, 对象句柄集, 环境变量, 基础优先级, 以及最大最小工作集. Windows中的线程是系统处理机调度的基本单位. 线程可以执行进程中的任意代码, 包括正在被其他线程执行的代码. 进程中的所有线程共享进程的虚拟地址空间和系统资源. 每个线程拥有自己的例外处理过程, 一个调度优先级以及线程上下文数据结构. 线程上下文数据结构包含寄存器值, 核心堆栈, 用户堆栈和线程环境块. 2) 如下图: 3)线程与进程的关系 线程是进程中的实体,一个进程可以拥有多个线程,一个线程必须有一个父进程。线程不拥有系统资源,只有运行必须的一些数据结构;它与父进程的其它线程共享该进程所拥有的全部资源。 在多中央处理器的系统里,不同线程可以同时在不同的中央处理器上运行,甚至当它们属于同一个进程时也是如此。 4) 进程和线程的区别   (1)、进程是资源管理的基本单位,它拥有自己的地址空间和各种资源,例如内存空间、外部设备;线程只是处理机调度的基本单位,它只和其他线程一起共享资源,但自己没有任何资源。   (2)、以进程为单位进行处理机切换和调度时,由于涉及到资源转移以及现场保护等问题,将导致处理机切换时间变长,资源利用率降低

JAVA多线程(四)--线程同步-Volatile

好久不见. 提交于 2020-03-01 07:36:10
1.cpu cache模型 cpu - 计算机的主内存(RAM), cpu速度变快,主内存没有跟上cpu的步伐,最终导致 cpu的处理速度和主内存的访问速度差距越来越大。 而cpu cache的出现解决了以上问题,同时引入了缓存不一致的问题。 比如:i++ 1)首先读取内存到cpu cache 2)进行i+1 3)将结果刷新到主内存中 在单线程中这个例子不会出现任何问题,但是在多线程的情况下就会出现问题。原因就是:每个线程都有自己的工作内存(本地内存,对应cpu cache模型中的cache),i在多个线程的本地内存中都会存在一个副本。 例:i 初始化为0;有两个操作A和B,都执行i++操作,按道理执行完之后i的值为2,但是就会有可能出现最后的结果i为1的情况,这就是缓存不一致的问题,要解决缓存不一致,我们有以下解决方式: 1)总线加锁 cpu和其他组建通信是通过总线来进行,采用总线加锁,会阻塞其他cpu对其他组件的访问,导致只有一个cpu抢到总线锁能够访问当前数据的内存。 2)通过缓存一致性协议(MESI)保证能够保证每一个缓存中使用到的共享变量副本是一致的,大致思想就是说当cpu操作cache中 的数据时,发现该数据是共享的,会进行如下操作: a. 读取操作,不用作任何处理 b. 写入操作,发出信号通知其他cpu将该变量的cache line置为无效状态

ThreadLocal理解和应用

谁说我不能喝 提交于 2020-03-01 07:11:13
本篇博客将为大家介绍一下ThreadLocal。从用途、使用方法、原理、及常见问题四个方面来介绍。 1.ThreadLocal用途 ThreadLocal用途可以理解成一个“储物间”,这个 “储物间”当中拥有大量的“储物柜 ”,每个“ 储物柜 ”实际上就是 每个线程 ,当中存放的是Thread线程中参数,针对于ThreadLocal的set方法 其实就是将参数放入到当前线程对应的“储物柜”当中(根据Thread.currentThread()进行区分线程) ,同样get()和remove()方法也是一样。 2.ThreadLocal使用方法 下面我们编写一个程序,每个线程保存一个自己的ID数据,然后多次调用进行修改ID数据并将其打印。 public class ThreadLocalIds { private static final ThreadLocal<AtomicInteger> THREAD_LOCAL = new ThreadLocal<AtomicInteger>() { protected AtomicInteger initialValue() { return new AtomicInteger(0);// threadlocal中初始化值,每个线程的ID都从0开始增加 }; }; public static int getIntValue() {

进程-线程-多线程-异步

蹲街弑〆低调 提交于 2020-03-01 06:58:07
进程-线程-多线程-异步 一、多线程的本质 1、并发多线程的启动、结束顺序 a、如何控制多线程的调用顺序 b、阻塞主线程等待子线程 二、异步操作的本质 三、线程 1、Thread 2、ThreadPool 3、Task 4、TaskFactory 5、Parallel 6、async await 语法糖 四、异常处理 五、线程取消 六、线程安全 一、多线程的本质 cpu的计算速度太快了导致硬件跟不上,就是木桶原理(盛水多少取决于最短板)。 cpu的计算能力很强,所以cpu可以分“时间片”,一个cpu可以分N+个时间片,每个时间片上跑一个线程(代码流)。cpu按顺序执行时间片,因为cpu太强,线程切换的太快,导致人感觉不出执行的卡顿,感觉上是多线程并发的。 微观角度:一个核同一时刻只能执行一个线程; 宏观角度: 是多线程并发的。 cpu分时间片执行线程,线程所需资源的不同会导致有 上下文的切换 ,其实上下文的切换会有性能的损失,但因为cpu计算能力超过其它硬件太多,不损失也是浪费。 扩展:4核8线程—核是物理的核,这里的线程是指虚拟核(一个核虚拟出2个核)。 1、并发多线程的启动、结束顺序 并发线程的启动是无序。 执行相同代码的并发线程的运行时间也不相同,所以结束时间也不同。 a、如何控制多线程的调用顺序 可以用委托提供的BeginInvoke方法,它是异步线程方法,并支持回调函数

偏向锁、轻量级锁、重量级锁区别与联系

百般思念 提交于 2020-03-01 05:53:55
今天总结了锁升级(偏向锁、轻量级锁、重量级锁)和锁优化下面开始总结。 其实这些内容都是JVM对锁进行的一些优化,为什么分开讲,原因是锁升级比较重要,也比较难。 一、锁升级 在1.6之前java中不存在只存在重量级锁,这种锁直接对接底层操作系统中的互斥量(mutex),这种同步成本非常高,包括操作系统调用引起的内核态与用户态之间的切换。线程阻塞造成的线程切换等。因此在jdk 1.6中将锁分为四种状态:由低到高分别为:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态。 1. 偏向锁。什么是偏向锁呢?为什么要引入偏向锁呢? 偏向锁是如果一个线程获取到了偏向锁,在没有其他线程竞争的情况下,如果下次再执行该同步块时则只需要简单判断当前偏向锁所偏向的对象是否是当前线程,如果是则不需要再进行任何获取锁与释放锁的过程,直接执行同步块。至于为什么引入偏向锁,是因为经过JVM的开发人员大量的研究发现大多数时候都是不存在锁竞争的,通常都是一个线程在使用锁的时候没有其他线程来竞争,然而每次都要进行加锁和解锁就会额外增加一些没有必要的资源浪费。为了降低这些浪费,JVM引入了偏向锁。 a) 偏向锁的获取以及升级过程如下: 当一个线程在执行同步块时,它会先获取该对象头的MarkWord,通过MarkWord来判断当前虚拟机是否支持偏向锁(因为偏向锁是可以手动关闭的),如果不支持则直接进入轻量级锁获取过程