志在指尖
用双手敲打未来

java多线程编程(多线程实现的四种方式)

java多线程编程

Java线程同步与异步
1.同步相关的办法有
wait,notify,notifyAll
2.关键字
synchronized
3.JDK锁的框架
AQS(AbstractQueuedSynchronizer)
4.AQS的完成类
java.util.concurrent.locks.ReentrantLock
java.util.concurrent.locks.ReentrantReadWriteLock
java.util.concurrent.CountDownLatch
java.util.concurrent.Semaphore
5.比如——两个线程替换打印出100以内的奇数和偶数
主程序:
clipboard.png
clipboard.png
输出成果示例:
clipboard.png



clipboard.png
考虑:
读者可以用两种其它办法完成,加深自己对Java线程同步和互斥的理解
用ReentrantLock?
仍是用wait和notify?
线程池
作用:
操控线程并发数量,一般用在操控单机并发度上,也是完成流控的一种计划;
完成原理:
1.参数含义
corePoolSize:中心线程的数量,在CPU密布型和IO密布型的使命中,这个参数的设置不太相同:
在CPU密布型的应用中:
一般这个参数被设置为:机器cpu核数-1,例如机器有4个核,这个参数就被设置为3,这样做的即统筹了最大的并发度,又统筹了其它非重要的中心使命的履行;
在IO密布的使命中:
一般这个参数被设置为机器cpu核数*(1.5-3),具体状况还需求根据实践事务状况进行压测比较,然后再给出最优的值;
maximumPoolSize:最大中心线程的数量
poolSize:当时线程的数量
当用户向线程池中新提交一个线程的时候,会有如下状况:
状况1.
假如当时线程池中线程的数量小于corePoolSize,就会创立一个新的线程,并添加到线程池中;
状况2.
假如当时线程池中线程的数量等于corePoolSize,而且等待行列中还没有满,则把当时用户添加的线程目标放在等待行列中;
状况3.
假如当时线程池中线程的数量大于等于corePoolSize而且小于maximunPoolSize,而且等待行列已经满,则创立一个新的线程,并添加到线程池中;
状况4.
假如当时线程池中线程的数量等于maximunPoolSize,则会根据线程创立线程时候的回绝策略,进行相应的处理;
2.java线程目标中run办法和start办法的区别:
2.1线程目标直接调用run办法,JVM是不会有感知,是不会直接发生一个新的线程,此刻程序运行的办法依然是串行的;
2.2线程目标直接调用start办法,JVM才会有感知,会发生一个新的线程,此刻才会发生并发多线程;
线程池正是充分使用了run办法和start的区别来完成线程的复用;
3.线程池的中心代码
下面均是以jdk1.6的线程池的源码,jdk1.7和jdk1.8线程池完成在上有些改变,但中心思维不变,有兴趣可以自己去研究
提交线程的中心代码:
clipboard.png
履行用户使命的中心代码:
clipboard.png
无锁化的完成计划
用线程池的计划
1.netty的reactor线程模型,参阅netty官方或网上相关的资料
2.异地机房数据库之间的数据同步:
用表名+主键名做hash,hash值相同的记载被写到同一个Kafka的Partition中去,假定一个Partition用一个线程进行消费,这样不同线程之间写入目标数据库的时候,就不会存在数据库行锁的竞赛关系,间接完成了无锁化的操作,即线程之间并行,线程内部串行,如下图所示;
clipboard.png
用CAS的命令
1.JDK中各种类型值的原子操作
AtomicInteger
AtomicLong
AtomicBoolean
2.jdk中各种锁的完成,本质也是volitate变量+CAS
java.util.concurrent.locks.ReentrantLock
java.util.concurrent.Semaphore
java.util.concurrent.CountDownLatch
散布锁的完成计划
1.tair
incr和decr操作,相当于是乐观锁
2.Redis/memcache
setNx命令
3.Zookeeper
充分使用watcher机制,创立暂时结点,谁创立成功,谁就获得当时的锁
4.数据库:使用数据库的行锁
//加锁SQL
updatetrade_basesetstatus=1wheretrade_no=“XXX”andstatus=0;
//解锁SQL
updatetrade_basesetstatus=0wheretrade_no=“XXX”andstatus=1;
留意trade_base表上一要有trade_no的列的唯一索引
当然具体用那种散布锁,还需求结合事务本身的需求,一般来说,在并发量不是别大,数据库完全可以扛得住的状况下,用数据库完成散布锁最快,最方便,而且功能的丢失也非常地小;
当然现在很多场景下,都是分库分表,而且加锁和解锁分别都只影响一行,对数据库来说,加锁和解锁的sql也是非常轻量的sql操作,因此在功能丢失上不用过多的忧虑。

java

多线程实现的四种方式

线程概述
运用多线程技术能够使体系一起运转多个程序块,缩短出程序呼应的时刻,进步计算机资源的运用率,达到多使命处理的目的。
进程和线程
进程是程序的一次动态履行过程,每个进程都有自己独立的内存空间。一个应用程序能够一起发动多个进程(比方浏览器能够开多个窗口,每个窗口便是一个进程)多进程操作体系能够运转多个进程,每个进程都能够循环运用所需求的CPU时刻片,使的一切进程看上去像在一起运转相同。线程是进程的一个履行流程,一个进程能够由多个线程组成,也便是一个进程能够一起运转多个不同的线程,每个线程完结不同的使命。线程的并发运转:便是一个进程内若干个线程一起运转。(比方:word的拼写查看功用和首字母主动大写功用是word进程中的线程)线程和进程的联系是一个部分和整体的联系,每个进程都由操作体系分配独立的内存地址空间,而同一进程的一切线程都在同一地址空间作业。
线程的生命周期
一个线程的完整生命周期要经历5中状况:新建、安排妥当、运转、堵塞、逝世
新建状况:运用new和某种线程的结构办法来创立线程目标,该线程就会进入新建状况,体系为该线程目标分配内存空间。处于新建状况的线程能够通过调用**start()**办法进入安排妥当状况。安排妥当状况:此时线程现已具备了运转的条件,进入了线程行列,等候体系分配CPU资源,一旦取得CPU资源,该线程就会进入运转状况。运转状况:进入运转在状况,线程会履行自己的**run()**办法中的代码。堵塞状况:一个正在履行的线程,如果履行了suspend、join或sleep办法,或等候io设备的运用权,那么该线程将会让出自己的CUP控制权并暂时中止自己的履行,进入堵塞状况。堵塞的线程,不能够进入安排妥当行列,只有当堵塞原因被消除的时候,线程才能进入安排妥当状况,从头进入线程行列中排队等候CPU资源,然后继续履行。逝世状况:一个线程完结了悉数作业或者被提早强制性的中止,该线程就处于逝世状况。线程常用办法归纳
多线程的完成办法
案例:
1、承继Thread类,重写run办法来完成多线程
运转成果:(根据4核计算机)
运转三个线程(次序履行)
运转6个线程(交互履行)
2、承继Runnable接口完成多线程
重写run办法,完成Runnable接口的完成类的实例目标作为Thread结构函数的target
运转成果:
承继Thread类和完成Runnable接口完结多线程的差异
完成Runnable接口能够做到资源共享,而承继Thread类不可(比方购票问题)完成Runnable接口相比承继Thread类来说,具有两大优势:避免单承继带来的限制和能够共享资源等优势相比Thread类的承继,一般采用完成Runnable接口来完成多线程
3、通过Callable和FutureTask创立线程
3.1创立Callable接口的完成类,完成它的Call办法
3.2运用FutureTask类来包装Callable目标,这个FutureTask目标需求封装Callable目标的Call办法的返回值
3.3运用FutureTask目标作为Thread目标的target创立并调用start办法发动线程
运转成果:
4、通过线程池完成多线程
运转成果:
关于线程注意事项
Java中,一切线程都是一起发动的,哪个线程占有CPU等运转资源,哪个线程就能够运转。Java程序每次运转都需求发动两个线程(main线程和废物收集器线程)Java线程运转过程中,其他线程并不会跟着主线程的完毕而完毕。

未经允许不得转载:IT技术网站 » java多线程编程(多线程实现的四种方式)
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

志在指尖 用双手敲打未来

登录/注册IT技术大全

热门IT技术

C#基础入门   SQL server数据库   系统SEO学习教程   WordPress小技巧   WordPress插件   脚本与源码下载