package com.smalltiger.juc;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Created by smalltiger on 2018/5/9.
* 一、i++的原子性问题:i++的操作实际上分为三个步骤“读-改-写”
* int i=10;
* i=i++;//10
*
* int temp=i;
* i=i+1;
* i=temp;
* 二、原子变量:java.util.concurrent.atomic 包下提供了常用的原子变量:
* 1.volatile修饰 :保证内存可见性
* 2.CAS(Compare-And-Swap)算法保证了数据的原子性
* CAS算法是硬件对于并发操作共享数据的支持
* CAS包含了三个操作数:
* 内存值V
* 预估值A
* 更新值B
* 当且仅当V==A时,V==B,否则,将不做任何操作
*/
public class TestAtomicDemo {
public static void main(String[] args) {
AtomicDemo ad=new AtomicDemo();
for (int i = 0; i < 10; i++) {
new Thread(ad).start();
}
}
}
class AtomicDemo implements Runnable{
//private int serialNumber=0;
private AtomicInteger serialNumber = new AtomicInteger();
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+getSerialNumber());
}
public int getSerialNumber() {
return serialNumber.getAndIncrement();
}
}
Callable创建线程
package com.smalltiger.juc;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* Created by smalltiger on 2018/5/9.
* 一:创建执行线程的方式三:实现Callable接口。相较于实现Runnable接口的方式,方法可以有返回值,并可以抛出异常。
*/
public class TestCallable {
public static void main(String[] args) {
ThreadDemo1 td = new ThreadDemo1();
//1.执行Callable方式,需要FutureTask实现类的支持,用于接受运算结果。
FutureTask<Integer> result = new FutureTask<Integer>(td);
new Thread(result).start();
//2.接受线程后运算结果
try {
Integer sum = result.get();
System.out.println(sum);
System.out.println("---------------");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class ThreadDemo1 implements Callable<Integer>{
@Override
public Integer call() throws Exception {
int sum=0;
for (int i = 0; i < 100000; i++) {
System.out.println(i);
sum+=i;
}
return sum;
}
}
模拟CAS算法
/**
* Created by smalltiger on 2018/5/9.
* 模拟CAS算法
*/
public class TestCompareAndSwap {
public static void main(String[] args) {
final CompareAndSwap cas=new CompareAndSwap();
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
int expectedValue=cas.get();
boolean b=cas.compareAndSet(expectedValue,(int)(Math.random()*101));
System.out.println(b);
}
}).start();
}
}
}
class CompareAndSwap{
private int value;
//获取内存值
public synchronized int get(){
return value;
}
//比较
public synchronized int compareAndSwap(int expectedValue,int newValue){
int oldValue=value;
if (oldValue==expectedValue){
this.value=newValue;
}
return oldValue;
}
//设置
public synchronized boolean compareAndSet(int expectedValue,int newValue){
return expectedValue==compareAndSwap(expectedValue,newValue);
}
}
volatile 关键字
package com.smalltiger.juc;
/**
* Created by smalltiger on 2018/5/9.
* 一:volatile 关键字:当多个线程进行操作共享数据时,可以保证内存中的数据是可见的。
* 相较于synchronized是一种轻量级的同步策略
* 注意:
* 1.volatile不具备“互斥性”
* 2.volatile不能保证变量的"原子性"
*/
public class TestVolatile {
public static void main(String[] args) {
ThreadDemo td=new ThreadDemo();
new Thread(td).start();
while (true){
if (td.isFlag()){
System.out.println("-----------");
break;
}
}
}
}
class ThreadDemo implements Runnable{
private volatile boolean flag=false;
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag=true;
System.out.println("flag="+isFlag());
}
public boolean isFlag(){
return flag;
}
public void setFlag(boolean flag){
this.flag=flag;
}
}
java多线程之读写锁
package com.smalltiger.juc;
import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Created by smalltiger on 2018/5/10.
*1.ReadWriteLock : 读写锁
*
* 写写/读写 需要"互斥"
* 读读 不需要互斥
*
*/
public class TestReadWriteLock {
public static void main(String[] args) {
ReadWriteLockDemo rw=new ReadWriteLockDemo();
new Thread(new Runnable() {
@Override
public void run() {
rw.set((int)(Math.random()*101));
}
},"Write").start();
for (int i = 0; i <100 ; i++) {
new Thread(new Runnable() {
@Override
public void run() {
rw.get();
}
}).start();
}
}
}
class ReadWriteLockDemo{
private int number=0;
private ReadWriteLock lock = new ReentrantReadWriteLock();
//读
public void get(){
lock.readLock().lock(); //上锁
try {
System.out.println(Thread.currentThread().getName()+":"+number);
}finally {
lock.readLock().unlock(); //释放锁
}
}
//写
public void set(int number){
lock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName());
this.number=number;
}finally {
lock.writeLock().unlock();
}
}
}
线程之共享变量-生产者,消费者代码之一(使用lock锁)
package com.smalltiger.juc;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by smalltiger on 2018/5/9.
*/
public class TestProductorAndConsumerForLock {
public static void main(String[] args) {
Clerk clerk = new Clerk();
Productor pro = new Productor(clerk);
Consumer cus = new Consumer(clerk);
new Thread(pro,"生产者 A").start();
new Thread(cus,"消费者 B").start();
new Thread(pro,"生产者 C").start();
new Thread(cus,"消费者 D").start();
}
}
//店员
class Clerk{
private int product=0;
private Lock lock = new ReentrantLock(); //创建同步锁
private Condition condition = lock.newCondition(); //创建同步锁的通信
//进货
public void get(){
lock.lock();
try {
while (product>=1){ //为了避免虚假唤醒问题,应该总是使用在循环中
System.out.println("产品已满!");
try {
condition.await();
} catch (InterruptedException e) {
}
}
System.out.println(Thread.currentThread().getName()+":"+ ++product);
condition.signalAll();
} finally {
lock.unlock();
}
}
//卖货
public void sale(){
lock.lock();
try {
while (product<=0){
System.out.println("缺货!");
try {
condition.await();
} catch (InterruptedException e) {
}
}
System.out.println(Thread.currentThread().getName()+":"+ --product);
condition.signalAll();
} finally {
lock.unlock();
}
}
}
//生产者
class Productor implements Runnable{
private Clerk clerk;
public Productor(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
for (int i = 0; i <20 ; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
clerk.get();
}
}
}
//消费者
class Consumer implements Runnable{
private Clerk clerk;
public Consumer(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
clerk.sale();
}
}
}
线程之共享变量-生产者,消费者代码之二
package com.smalltiger.juc;
/**
* Created by smalltiger on 2018/5/9.
*/
public class TestProductorAndConsumer {
public static void main(String[] args) {
Clerk clerk = new Clerk();
Productor pro = new Productor(clerk);
Consumer cus = new Consumer(clerk);
new Thread(pro,"生产者 A").start();
new Thread(cus,"消费者 B").start();
new Thread(pro,"生产者 C").start();
new Thread(cus,"消费者 D").start();
}
}
/*//店员
class Clerk{
private int product=0;
//进货
public synchronized void get(){
while (product>=1){ //为了避免虚假唤醒问题,应该总是使用在循环中
System.out.println("产品已满!");
try {
this.wait();
} catch (InterruptedException e) {
}
}
System.out.println(Thread.currentThread().getName()+":"+ ++product);
this.notifyAll();
}
//卖货
public synchronized void sale(){
while (product<=0){
System.out.println("缺货!");
try {
this.wait();
} catch (InterruptedException e) {
}
}
System.out.println(Thread.currentThread().getName()+":"+ --product);
this.notifyAll();
}
}
//生产者
class Productor implements Runnable{
private Clerk clerk;
public Productor(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
for (int i = 0; i <20 ; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
clerk.get();
}
}
}
//消费者
class Consumer implements Runnable{
private Clerk clerk;
public Consumer(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
clerk.sale();
}
}
}*/
自定义ForkJoin方法
package com.smalltiger.juc;
import org.junit.Test;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.stream.LongStream;
/**
* Created by smalltiger on 2018/5/10.
*/
public class TestForkJoinPool {
//自定义ForkJoin方法
public static void main(String[] args) {
Instant start = Instant.now();
ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask<Long> task = new ForkJoinSumCalculate(0L,100000000000L);//7045->14308
Long sum = pool.invoke(task);
System.out.println(sum);
Instant end = Instant.now();
System.out.println("耗费时间为: "+ Duration.between(start,end).toMillis());
}
//普通单线程for循环
@Test
public void test1(){
Instant start = Instant.now();
long sum = 0L;
for (long i = 0L; i <=100000000000L; i++) { //13155->26236
sum+=i;
}
System.out.println(sum);
Instant end = Instant.now();
System.out.println("耗费时间为: "+ Duration.between(start,end).toMillis());
}
//java8新特性
@Test
public void test2(){
Instant start = Instant.now();
Long sum = LongStream.rangeClosed(0L,100000000000L)//3842->7830
.parallel()
.reduce(0L,Long::sum);
System.out.println(sum);
Instant end = Instant.now();
System.out.println("耗费时间为: "+ Duration.between(start,end).toMillis());
}
}
class ForkJoinSumCalculate extends RecursiveTask<Long>{
private long start;
private long end;
private static final long THURSHOLD=10000L;//临界值
public ForkJoinSumCalculate(long start, long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
long length = end-start;
if (length<=THURSHOLD){
long sum=0L;
for (long i = start; i <=end; i++) {
sum+=i;
}
return sum;
}else{
long middle = (start+end)/2;
ForkJoinSumCalculate left = new ForkJoinSumCalculate(start,middle);
left.fork();//进行拆分,同时压入线程队列
ForkJoinSumCalculate right = new ForkJoinSumCalculate(middle+1,end);
right.fork();
return left.join()+right.join();
}
}
}
CountDownLatch:闭锁
package com.smalltiger.juc;
import java.util.concurrent.CountDownLatch;
/**
* Created by smalltiger on 2018/5/9.
* CountDownLatch:闭锁,在完成某些运算时,只有其他所有线程的运算全部完成,当前运算才继续执行
*/
public class TestCountDownLatch {
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(50);
LatchDemo ld=new LatchDemo(latch);
long start=System.currentTimeMillis();
for (int i = 0; i <50 ; i++) {
new Thread(ld).start();
}
try {
latch.await();
} catch (InterruptedException e) {
}
long end=System.currentTimeMillis();
System.out.println("耗费时间为:"+(end-start));
}
}
class LatchDemo implements Runnable{
private CountDownLatch latch;
public LatchDemo(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
synchronized (this) {
try {
for (int i = 0; i < 50000; i++) {
if (i%2==0){
System.out.println(i);
}
}
} finally {
latch.countDown();
}
}
}
}
线程经典题目: 编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A、B、C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示。 *如:ABCABCABC…… 依次递归
package com.smalltiger.juc;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by smalltiger on 2018/5/9.
* 编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A、B、C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示。
*如:ABCABCABC…… 依次递归
*/
public class TestABCAlternate {
public static void main(String[] args) {
AlternateDemo ad = new AlternateDemo();
new Thread(
new Runnable() {
@Override
public void run() {
for (int i = 0; i <=20; i++) {
ad.loopA(i);
}
}
},"A"
).start();
new Thread(
new Runnable() {
@Override
public void run() {
for (int i = 0; i <=20; i++) {
ad.loopB(i);
}
}
},"B"
).start();
new Thread(
new Runnable() {
@Override
public void run() {
for (int i = 0; i <=20; i++) {
ad.loopC(i);
System.out.println("-----------");
}
}
},"C"
).start();
}
}
class AlternateDemo{
private int number =1;//当前正在执行线程的标记
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
/*
*@param totalLoop:循环第几轮
*/
public void loopA(int totalLoop){
lock.lock();
try {
//1.判断
if (number!=1){
condition1.await();
}
//2.打印
for (int i = 1; i <=1; i++) {
System.out.println(Thread.currentThread().getName()+"\t"+i+"\t"+totalLoop);
}
//3.唤醒
number=2;
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void loopB(int totalLoop){
lock.lock();
try {
//1.判断
if (number!=2){
condition2.await();
}
//2.打印
for (int i = 1; i <=1; i++) {
System.out.println(Thread.currentThread().getName()+"\t"+i+"\t"+totalLoop);
}
//3.唤醒
number=3;
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void loopC(int totalLoop){
lock.lock();
try {
//1.判断
if (number!=3){
condition3.await();
}
//2.打印
for (int i = 1; i <=1; i++) {
System.out.println(Thread.currentThread().getName()+"\t"+i+"\t"+totalLoop);
}
//3.唤醒
number=1;
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}