java多线程
先聊以下CAS:CAS:compare and swap:就是比较并且交换 这里用到三个值,一个是内存里面的值,一个是预期的旧值,一个是新值,当内存里面的值等于预期的旧值的时候,便将原子值设置为新值。
下面是几种多线程的同步方式:
1.synchronized(独占锁)
2.lock(高级同步机制)
3.atomicInteger(非阻塞)
4.semaphore(高级同步对象)
synchronized:每次只允许一个线程进入
wait():让当前线程释放锁并进入阻塞状态
notify():随机唤醒一个被阻塞的线程,并将该线程放入锁等待池
notifyall():唤醒所有的被阻塞的线程,并将他们放入锁等待池
class Test{
void show(){
synchronized (Test.class){//这里需要一个锁对象,当一个线程进入该代码块以后,其他线程不能进如该代码块,只能再外面等待
System.out.println("11111");
}
}
}
lock:互斥锁,比synchronized扩展性更高,但是需要手动释放锁
lock():给当前代码上锁,获取锁的线程进入并执行,没有获取锁的线程等待锁的释放
unlock():释放锁,
readlock():获取读锁
writelock():获取写锁
读锁和写锁嗾使来自ReentrantReadWriteLock类
lock.lock();//上锁,当上了锁之后,其他线程就布恩那个访问该方法处于阻塞状态
if (single == 1) {
System.out.print("1");
System.out.print("1");
System.out.print("1");
System.out.print("1");
System.out.println("");
try {
c.await();
single = 2;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (single == 2) {
c1.signal();
}
lock.unlock();//解锁,解锁完以后,其他线程都可以进入
atomicInteger:利用了ACS对整数的操作包装为原子性,CAS便是用了atomicInteger的compareAndSet()方法
compareAndSet():比较当前值是否等于预期值,相等便将该值原子设置为新值get():获取当前值
incrementAndGet():原子上增加一个当前值,并返回一个新值
class Test{
private AtomicInteger atomicInteger=new AtomicInteger(10);//初始值为10
void show(){
System.out.println(Thread.currentThread().getName()+"-----"+atomicInteger.incrementAndGet());//原子的值上加一并输出结果
}
public static void main(String[] args) {
Test test=new Test();
new Thread(){
@Override
public void run() {
while (true){
test.show();
}
}
}.start();
new Thread(){
@Override
public void run() {
while (true){
test.show();
}
}
}.start();
}
}
semaphore:利用信号量计数器来经行多线程操作
acquire():获取许可证,并将信号量-1
release():释放许可证,并将信号量+1
下面实现一个小的上厕所实验:
class FF{
Lock lock=new ReentrantLock();//创建一个锁对象
Semaphore semaphore;//创建资源对象,即创建厕所数量
boolean single[];//创建资源对象的状态,即该厕所有没有人上
public FF(Semaphore semaphore, boolean[] single) {
this.semaphore = semaphore;
this.single = single;
}
void show() throws InterruptedException {
semaphore.acquire();//调用acquire方法获取许可证,默认一开始是1,通俗来讲就是看看有没有空位的厕所,这里你要用厕所,所以他会-1,如过结果是0表示没有位置了,则其他线程不能进入
int i=show1();//获取当前有空位厕所的索引
System.out.println(Thread.currentThread().getName()+"上了"+i+"号厕所");
Thread.sleep(1000);//相当于上厕所时间
single[i]=false;//上完以后该厕所变为空的,所以赋值为false
semaphore.release(); //释放许可证返回给信号量这里因为上完了所以信号量+1
}
int show1() {//这个是返回有空位的厕所的索引
lock.lock();//上锁,避免你现在找的时候别人也进来找发生冲突
int j = 0;//设有空位的厕所的索引是0
for (int i = 0; i < single.length; i++) {
if (single[i] != true) {
j = i;//判断厕所有没有空位,有的话就返回i,并将该位置设为true表示有人了
single[i] = true;
break;
}
}
lock.unlock();//释放锁,让别的人来找
return j;
}
public static void main(String[] args) {
FF f=new FF(new Semaphore(10,true),new boolean[10]);//创建一个信号量对象,里面声明了资源数量为10就是由10个厕所,后面的true是设置该锁位公平锁,如果写false就是非公平锁。
ExecutorService executorService = Executors.newCachedThreadPool();//创建线程池
for (int i = 0; i < 100; i++) { //假如有100个人同时上厕所
executorService.execute(new Thread(){
@Override
public void run() {
try {
f.show();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}