package 读写锁;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
public class readwritelock {
public static void main(String[] args) {
// TODO 自动生成的方法存根
//读写锁 可分配一写多读的同步锁。读写分离。可多次分配读锁。写锁互斥
//写写互斥 读写互斥 读读不互斥 支持重入
/*
//先拿互斥锁做例子: 读写都阻塞,一个一个地执行
student s = new student(100);
Callable<Object> writetask = new Callable<Object>() {
@Override
public Object call() throws Exception {
s.setValue(111);
return null;
}
};
Callable<Object> readtask = new Callable<Object>() {
@Override
public Object call() throws Exception {
s.getValue();
return null;
}
};
ExecutorService es = Executors.newFixedThreadPool(20);//创建线程池
long start = System.currentTimeMillis();//时间获取 ms
for (int i = 0; i < 2; i++) {//2次写任务
es.submit(writetask);
//虽然是线程池,但是setValue方法是加锁的,同时只能一个线程有锁标记
//因而时间为2s
}
for (int i = 0; i < 18; i++) {//18次读任务
es.submit(readtask);
//与写任务同理 18s 一共20s
}
es.shutdown();//关闭线程池 将现有任务执行完毕,不接受新任务
while(true) {
if (es.isTerminated()) {//如果现有任务都执行完了,则返回true
break;
}
}
System.out.println(System.currentTimeMillis()-start);//计算时间差
*/
//下面拿读写锁改良:
student2 s = new student2(111); //除了这一行都一样
Callable<Object> writetask = new Callable<Object>() {
@Override
public Object call() throws Exception {
s.setValue(111);
return null;
}
};
Callable<Object> readtask = new Callable<Object>() {
@Override
public Object call() throws Exception {
s.getValue();
return null;
}
};
ExecutorService es = Executors.newFixedThreadPool(20);//创建线程池
long start = System.currentTimeMillis();//时间获取 ms
for (int i = 0; i < 2; i++) {//2次写任务
es.submit(writetask);//写锁互斥 所以2s
}
for (int i = 0; i < 18; i++) {//18次读任务
es.submit(readtask);
//读锁不互斥 线程池有20个=18+2个线程,所以1s 一共3s
}
es.shutdown();//关闭线程池 将现有任务执行完毕,不接受新任务
while(true) {
if (es.isTerminated()) {//如果现有任务都执行完了,则返回true
break;
}
}
System.out.println(System.currentTimeMillis()-start);//计算时间差
}
}
class student {
ReentrantLock locker = new ReentrantLock();
int value;
//读
public int getValue() {
locker.lock();
try {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return value;
}
finally {
locker.unlock();
}
}
//写
public void setValue(int value) {
locker.lock();
try {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
this.value = value;
}
finally {
locker.unlock();
}
}
public student(int value) {
this.value = value;
}
}
class student2 {
//ReentrantLock locker = new ReentrantLock();
ReentrantReadWriteLock locker = new ReentrantReadWriteLock();//可重写 读写锁
ReadLock readlocker = locker.readLock();//从 读写锁 取出 读锁
WriteLock writelock = locker.writeLock();//从 读写锁 取出 写锁
//读锁 和 写锁 是一套锁 都是从读写锁中取出来的 所以有互斥效果
int value;
//读
public int getValue() {
readlocker.lock();
try {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return value;
}
finally {
readlocker.unlock();
}
}
//写
public void setValue(int value) {
writelock.lock();
try {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
this.value = value;
}
finally {
writelock.unlock();
}
}
public student2(int value) {
this.value = value;
}
}
package 线程与进程;
public class getsomthing {
String cardid;
String password;
double money;
String name;
public getsomthing(String carid, String password,double money) {
this.cardid = carid;
this.password = password;
this.money = money;
}
public void getmoney(String carid, String password,double money) {
if(carid.equals(this.cardid) && password.equals(this.password)) {
System.out.println("验证成功");
if(money <= this.money) {
//如果到这,girlget放弃时间片,boyget得到时间片直到取出money,之后girl
//得到时间片,会再次取出,则剩余金额为负数
/*多线程并发访问临界资源(共享资源),当破坏了原子操作(临界资源
要做的事情 ),可能导致数据不一致*/
//解决办法:同时只能有1个线程访问 中间进行原子操作 使用“同步代码块”
/*
* synchronized (临界资源对象) {//对临界资源对象加锁
* //原子操作
* //此时临界资源对象为 card (girlget 和 boyget中的 card)
* }
* */
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}//人为干预,让进程在这断一次
this.money-=money;
System.out.println("取出"+money+",剩余"+this.money);
}
else {
System.out.println("余额不足");
}
}
}
}
package 线程与进程;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class main {
public static void main(String[] args) throws InterruptedException {
// TODO 自动生成的方法存根
//一个进程可以有多个线程 比如百度网盘可以同时下载多个文件
/******************************************************
//创建线程 方法1 继承Thread类
mythread t1 = new mythread(1);
mythread t2 = new mythread(2);
//t1.run();
//t2.run();//只是普通的方法调用,这不叫多线程
t1.start();//启动线程
t2.start();
for(int i=0;i<=20;i++)
{
System.out.println("main "+" : "+i);
}//主线程的,3线程并列执行
*******************************************************/
/******************************************************
//创建线程 方法2
runnable_thread task = new runnable_thread();//task任务
Thread t1 = new Thread(task);//使用Thread的构造方法
t1.start();
runnable_thread task2 = new runnable_thread();//task任务
Thread t2 = new Thread(task2);//使用Thread的构造方法
t2.start();
*****************************************************/
//线程常用方法
/**
//sleep()休眠
mythread t1 = new mythread(1);
mythread t2 = new mythread(2);
t1.start();
t2.start();
System.out.println("start");
Thread.sleep(2000);//本进程休眠2秒
for(int i=0;i<10;i++)
{
System.out.println("main:"+i);
}
System.out.println("end");
**/
/**
//yield()主动放弃时间片
Thread t1 =new Thread(new task1());
Thread t2 =new Thread(new task2());
t1.start();
t2.start();
**/
/**
//join()等待线程终止
Thread t1 =new Thread(new task1());
Thread t2 =new Thread(new task2());
t1.start();
for(int i=0;i<=100;i++)
{
System.out.println("main: "+i);
if(i==50) {
t1.join();//将t1加入到main中来,等待t1线程结束后,再执行
}
}
**/
/*
//synchronized 同步代码块 加锁
//但可能出现几个问题:
// 1.死锁 第一个线程有A对象所标记,想要B对象所标记 时间片到期
// 第二个线程有B对象所标记,想要A对象所标记 都进入阻塞状态。
// 解决办法,线程间的通信 等待 通知
// wait() 在一个线程中,调用 obj.wait时,此线程释放所有锁标记
// notify() notifyAll() 从obj的waitting中释放一个或全部线程,对自身无影响
getsomthing card = new getsomthing("123456", "654321", 1000.0);
Thread t1 = new Thread(new girlget(card));
Thread t2 = new Thread(new boyget(card));
t1.start();
t2.start();
*/
/*
//下面测试线程通信代码
//可利用此解决死锁现象
Object o = new Object();
tongxin t1 = new tongxin(o);
t1.start();
Thread.sleep(1000);
synchronized (o) {
System.out.println("main进入同步代码块");
o.notify();//从那些因为o对象而进入无限期等待的线程中,营救一个出来
//notifyAll救出所有 notify只救出一个
System.out.println("main退出同步代码块");
*/
/*
//lock锁 和 synchronized同步代码块加锁类似
//ReentrantLock重入锁,支持重入
//即一个线程拿到锁后,递归调用,此线程可以重复拿锁,但是,最后释放锁的次数需和拿锁次数相同
//释放少一次都会死锁
//ReentrantLock是Lock接口的实现类
Lock locker = new ReentrantLock();//创建重入锁对象
try {
locker.lock();//开启锁 相当于synchronized(this){
//中间填写需要保护的内容
//但是 如果中间抛出了异常,程序结束,那么就会产生死锁 即再也拿不到锁
//解决方法:unlock写道try finally结构的finally中
}
finally {
locker.unlock();//释放锁 相当于}
}
*/
}
}
class mythread extends Thread{
private int n=0;
public mythread(int n) {
this.n=n;
}
@Override
public void run() {
for(int i=0;i<=30;i++)
{
System.out.println("mythread "+n+" : "+i);
}
}
}
class runnable_thread implements Runnable{
@Override
public void run() {
// TODO 自动生成的方法存根
for(int i=0;i<=20;i++)
{
System.out.println("runnable_thread: "+i);
}
}
}
class task1 implements Runnable{
@Override
public void run() {
// TODO 自动生成的方法存根
for(int i=0;i<=100;i++)
{
System.out.println("task1: "+i);
}
}
}
class task2 implements Runnable{
@Override
public void run() {
// TODO 自动生成的方法存根
for(int i=0;i<=100;i++)
{
System.out.println("---task2: "+i);
if(i%10==0)
{
Thread.yield();//主动放弃时间片
}
}
}
}
class girlget implements Runnable {
getsomthing card;
public girlget(getsomthing card) {
this.card = card;
}
@Override
public void run() {
synchronized (card) {//使每个对象有个互斥锁标记
this.card.getmoney("123456", "654321", 500.0);
}
}
}
class boyget implements Runnable {
getsomthing card;
public boyget(getsomthing card) {
this.card = card;
}
@Override
public void run() {
synchronized (card) {//没有锁标记时
this.card.getmoney("123456", "654321", 700.0);
}
}
}
class tongxin extends Thread{
Object obj;
public tongxin(Object obj) {
this.obj= obj;
}
@Override
public void run() {
// TODO 自动生成的方法存根
System.out.println("线程启动");
synchronized (obj) {
System.out.println("进入同步代码块");
try {
obj.wait();//主动释放无限期等待 后面不会运行
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println("退出同步代码块");
}
System.out.println("线程结束");
}
}