java学习-线程与进程

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("线程结束");
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

静安书以沫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值