Java多线程代码

目录

 

创建多线程第一种方法:

创建多线程第二种方法:

多线程同步:

多线程通信:


创建多线程第一种方法:

package Multiple__Thread;
/*
 * 进程:是程序一次的运行
 * 多线程:是一个进程里的多个线程进行操作
 * 
 * 创建的第一种方法:继承Thread类,重写run方法
 * Thread有以下方法:
 * 
 * start():开始线程	
 * sleep(long millis):休眠当前正在执行线程,millis为休眠毫秒数
 * join():老大加入(A线程中B线程调用join()方法,必须等B执行完后才能执行A线程)
 * yield():暂停当前正在执行线程,可能又被当前线程抢占CPU,也可能被其它线程抢占CPU
 * interrupt():从等待状态中退出
 * isAlive():判断当前线程是否存在
 * 
 * currentThread():返回当前线程(静态方法)
 * setName(String):设置线程名字
 * getName():返回线程名字
 * 
 * setPriority(int newPriority):设置线程优先级(默认为5,最低1,最高10)
 * getPriority():返回当前线程优先级
 */
//创建一个子线程,和主线程一起输出1-100的正整数
class MyThread extends Thread{
	public void run() {
		for(int i=1;i<=100;i++) {
			try {
				Thread.currentThread().sleep(1000);	//执行时休眠1000毫秒
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+Thread.currentThread().getPriority()+":"+i);
		}
	}
}
public class CreateWay {
	public static void main(String[] args) throws InterruptedException {
		MyThread m=new MyThread();
		//m.run();	//错误:若此时执行run()只是调用对象的run方法,不会创建一个线程
		m.start();
		
		//修改主线程,子线程名称
		m.setName("子线程");
		Thread.currentThread().setName("========主线程");
		if(m.isAlive()) {System.out.println("子线程未执行完毕");}	//判断子线程是否存在
		//主线程 
		Thread.currentThread().setPriority(10); 		//设置优先级后,明显主线程抢占CPU较快
		for(int i=1;i<=100;i++) {
			if(i%10==0) {Thread.currentThread().yield();}	//当i为10的倍数时,看看主线程子线程哪个能否抢占CPU
			System.out.println(Thread.currentThread().getName()+Thread.currentThread().getPriority()+":"+i);
			if(i==80) {m.join();}	//子线程变大佬加入,只能等大佬执行完后主线程再执行
		}
		if(!m.isAlive()) {System.out.println("子线程已执行完毕");}
	}
}

创建多线程第二种方法:

package Multiple__Thread;
/*
 * 多线程的另一方式(也是常用方式):接口Runnable提供了run()方法,且只有run()方法
 * 优点:
 * 1、当线程类已经继承于某个类,但是仍然想实现多线程可用此方式
 * 2、多个线程能共享一个对象的资源(在Thread方式里要设置为静态变量)
 * 
 * 本质(总结):只有Thread类才能实现线程,要么继承它,要么利用Thread的构造函数与Runnable接口进行复制
 */

//既继承了基类,又实现了接口Runnable的run()方法
class People{
}
class Student extends People implements Runnable{
	public void run() {
		System.out.println("我是学生类");
	}
	public void show() {
		System.out.println("hhh");
	}
}
//共享资源例子(继承Thread方式):火车票分四个窗口售出
class WindowThread extends Thread{
	int ticket=100;
	//static int ticket=100;	//当不设置为static变量时达不到共享一个类资源的效果,并且设置成static消耗较大,jvm不会回收
	public void run() {
		while(ticket>0)
		System.out.println(Thread.currentThread().getName()+"窗口正在售出第"+(ticket--)+"张票");
	}
}
//共享资源例子(实现Runnable接口方式):火车票分四个窗口售出
class Window implements Runnable{
	private int ticket=100;
	public void run() {
		while(ticket>0) {
		System.out.println(Thread.currentThread().getName()+"窗口正在售出第"+(ticket--)+"张票");
		}
	}
}
public class CommonCreateWay {

	public static void main(String[] args) {
		//设置四个窗口
		/*WindowThread w1=new WindowThread();
		WindowThread w2=new WindowThread();
		WindowThread w3=new WindowThread();
		WindowThread w4=new WindowThread();
		w1.start();w2.start();w3.start();w4.start();*/
		
		Window w=new Window();			//设置一个总窗口
		Thread t=new Thread(w,"窗口1");	//用四个Thread线程构造四个窗口
		t.start();
		t=new Thread(w,"窗口2");
		t.start();
		t=new Thread(w,"窗口3");
		t.start();
		t=new Thread(w,"窗口4");
		t.start();
		
	}

}

多线程同步:

package Multiple__Thread;
/*
 * 线程有几个状态:出生态(刚被创建出来),就绪态(调用start()方法后开始抢夺CPU资源),运行态(正在被运行的线程),死亡态(结束线程)
 * 阻塞态(执行一半被搁置的状态):调用wait(),join(),sleep()等出现状态
 * 
 * 当线程进入阻塞态时,可能就会引起线程安全问题。
 * 这时就需要一个同步机制:
 * 一、同步代码块:当操作共享资源时,突然进入阻塞状态会引起安全问题,就需要同步代码块使得一个线程执行完毕后
 * 另一线程才能执行。
 * 格式:synchronized(任意对象){	//一般称此对象为锁,锁住共享资源只能供一人使用
 * 		同步的代码块(一般为操作共享资源的代码块)
 * }
 * 
 * 二、同步方法:锁为当前对象(this)
 * 	格式:权限 synchronized 返回值 方法名()
 * }
 * 
 * 单例模式:属于工厂模式的特例,只是它不需要输入参数并且始终返回同一对象的引用(即某类在系统中只有一个实例)
 * 饿汉式:在程序启动或单件模式类被加载的时候,单例模式实例就已经被创建。
 * 懒汉式:当程序第一次访问单例模式实例时才进行创建
 * 若该对象经常被访问使用饿汉式,若该对象不经常被访问使用懒汉式。
 */
//进入阻塞状态后出现的错误
class DangerousWindow implements Runnable{
	private int ticket=100;
	public void run() {
		while(ticket>0) {
		try {
			Thread.sleep(15);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"窗口正在售出第"+(ticket--)+"张票");
		}
	}
	}
class SatefyWindow implements Runnable{
	private int ticket=100;
	Object obj=new Object();
	public void run() {
			//同步代码块
			while(true) {
				try {
					Thread.sleep(20);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				synchronized(obj) {	//若同步放在while上面即函数开始,会导致只有一个窗口能售票,因为
									//其它窗口刚想售票时(抢夺CPU时)共享资源和CPU会马上被锁住
				if(ticket>0) {				
					
					System.out.println(Thread.currentThread().getName()+"窗口正在售出第"+(ticket--)+"张票");
				}
				else {break;}
			}
			}
			//同步方法
			/*while(true) {
			try {
				Thread.sleep(15);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
				sale();
			}*/
		}
	public synchronized void sale() {
		if(ticket>0) {				
			
			System.out.println(Thread.currentThread().getName()+"窗口正在售出第"+(ticket--)+"张票");
		}
	}
}
//饿汉式
class Hungry_Single{
	private static Hungry_Single single=new Hungry_Single();
	public static Hungry_Single get_Single() {
		return single;
	}
}
//懒汉式(容易引起多线程问题,要使用同步机制)
class Lazy_Single{
	private static Lazy_Single single=null;
	public static Lazy_Single get_Single() {
		if(single==null) {		//让其它线程知道接下来是一个同步代码块,不为空时不用跟着浪费时间,不用处于等待态
		//静态方法里没法使用this,所以使用Lazy_Single.class,一样效果
		synchronized(Lazy_Single.class) {
			if(single==null) {
				single=new Lazy_Single();
			}
		}
		}
		return single;
	}
}
//练习题目:银行有一个账户,有俩个人分别向同一账户存3000元,每次存1000,分三次,每次存完打印账户余额
/*
 * 分析:	是否有多线程?有,俩个人。
 * 			是否有共享资源?有,一个账户。
 * 			是否需要同步机制?需要,当其中一个人操作账户时其它人不能操作
 */
class Account{
	protected float money=0;
	public void save_money(float money) {this.money+=money;
	System.out.println("当前账户余额:"+this.money);}
	public float get_money() {return money;}
}
class Custom implements Runnable{
	Account a;
	Custom(Account a){this.a=a;}
	public synchronized void run() {
		//当第一线程刚执行完存钱操作后,第二线程又马上进行判断和存钱操作,会引起错误。
		while(a.get_money()<3000)	//当余额高于3000时不必执行以下操作
		{
			a.save_money(1000);
		}
	}
	
}
public class synchronized_ {
	public static void main(String args[]) {
		//DangerousWindow w=new DangerousWindow();			//设置一个总窗口
		SatefyWindow w=new SatefyWindow();					//设置一个总窗口
		Thread t=new Thread(w,"窗口1");	//用四个Thread线程构造四个窗口
		t.start();
		t=new Thread(w,"窗口2");
		t.start();
		t=new Thread(w,"窗口3");
		t.start();
		t=new Thread(w,"窗口4");
		t.start();
		
		//测试饿汉懒汉
		/*Hungry_Single h1=Hungry_Single.get_Single();
		Lazy_Single h2=Lazy_Single.get_Single();*/
		
		//练习题目测试
		/*Account account=new Account();
		Custom c=new Custom(account);
		Thread t1=new Thread(c);
		Thread t2=new Thread(c);
		t1.start();t2.start();*/
	}
}

多线程通信:

package Multiple__Thread;
/*
 * 死锁:是指俩个线程互相有依赖状态,各自进入阻塞态时都在等待对方的锁
 * 避免死锁:1、同步区域拥有各自的锁2、同步代码块用完操作资源后立马释放
 * 
 * 多线程通信(合作):当多个线程需要协作操作同一内存资源(类)时,必须使用通信机制,防止某一线程占用CPU太多出现的问题
 * 通信机制有以下方法:
 * wait():使当前线程进入阻塞态,并释放锁。
 * notify():通知该锁第一个调用wait()线程苏醒(可被其它线程通知,实现一个通信效果)
 * notifyAll():通知该锁所有调用wait()线程苏醒(可被其它线程通知,实现一个通信效果)
 * 注意: 1、以上方法必须和while搭配使用,保证安全性,防止在wait()之前notify()就来通知苏醒
 * 		 2、以上方法的调用对象必须是同步锁对象,否则就会引起异常
 * 		 3、以上方法必须在try catch里使用
 * wait()和sleep()和yield()的区别:yield()是释放CPU当前执行线程,使线程进入就绪态
 * sleep()是使当前CPU执行线程进入阻塞态,wait()是使当前CPU执行线程进入阻塞态,并释放锁(即此时其它线程可进入同步代码)。
 */
//多线程通信
class Storage{
	protected int number[]=new int[20];
	protected int putcount=0,getcount=0;	//记录进出数组数据量
	protected int size=0;	//记录当前数组的规模(数据数),某一线程过快,每放入或取出数据
							//达到数组规模(满或空状态)时休眠一次
	Object putlock=new Object();
	Object getlock=new Object();
	synchronized void put(int num) {
		try {
			while(size==number.length) {
				this.wait(); 		//当前数组规模已达容量值,休眠线程
			}
			if(putcount==number.length) {
				putcount=0;			//达到一个循环数组的效果
			}
			number[putcount++]=num;
			size++;	//更新规模
			System.out.println("向数组放入第"+size+"个元素:"+num);
			this.notify(); 			//从while循环退出后,规模不为满,可以唤醒线程
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
	synchronized int get() {
		int temp = 0;
		try {
			while(size==0) {
				this.wait(); 		//当前数组规模已为0,线程休眠
			}
			if(getcount==number.length) {
				getcount=0;			//达到一个循环数组的效果
			}
			temp=number[getcount];
			getcount++;
			size--;	//更新规模
			System.out.println("从数组取出第"+size+"个元素:"+temp);
			this.notify(); 			//从while循环退出后,规模不为空,可以唤醒线程
		}catch(Exception e) {
			e.printStackTrace();
		}
		return temp;
	}
}
class put_Thread implements Runnable{
	private Storage st;
	put_Thread(Storage st){this.st=st;}
	public synchronized void run() {
		while(true) {
		st.put(0);
		}
	}

}
class get_Thread implements Runnable{
	private Storage st;
	get_Thread(Storage st){this.st=st;}
	public synchronized void run() {
		while(true) {
		st.get();
		}
	}
	
}
public class deadlock_cooperation {
	//死锁例子:美国人和中国人收集工具,美国人进入阻塞态需要筷子,中国人进入阻塞态需要刀
	static class deadlock implements Runnable{
		private Object chopstickslock=new Object();
		private Object knifelock=new Object();
		boolean judge;
		deadlock(boolean judge){this.judge=judge;}
		public void run() {
			if(judge) {
				while(true) {
					synchronized(chopstickslock) {
					System.out.println("中国人已有筷子");
					//因CPU执行速度太快,必须暂缓一会模拟死锁
					try {
						Thread.sleep(6000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
						synchronized(knifelock) {
							System.out.println("中国人已有筷子已有刀叉");
						}
					}
				}
			}
			else {
				while(true) {
				synchronized(knifelock) {
					System.out.println("美国人已有刀叉");
					//因CPU执行速度太快,必须暂缓一会模拟死锁
					try {
						Thread.sleep(6000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					synchronized(chopstickslock) {
						System.out.println("美国人已有刀叉已有筷子");
					}
				}
				}
			}
		}
	}
	
	public static void main(String[] args) {
		//测试死锁
		/*deadlock China=new deadlock(true);
		deadlock America=new deadlock(false);
		Thread Copen=new Thread(China);
		Thread Aopen=new Thread(America);
		Copen.start();Aopen.start();*/
		
		//测试通信
		Storage s=new Storage();				//s即为同一块内存空间
		put_Thread put=new put_Thread(s);		//放入线程通过构造方式操纵同一块内存空间(类s)
		get_Thread get=new get_Thread(s);		//取出线程通过构造方式操纵同一块内存空间(类s)
		Thread t1=new Thread(put);
		Thread t2=new Thread(get);
		t1.start();t2.start();
	}
}
/*
 * 通信结果:当放入至20个元素时,线程等待,当取出线程已取完时,取出线程等待
			向数组放入第1个元素:0
			向数组放入第2个元素:0
			向数组放入第3个元素:0
			向数组放入第4个元素:0
			向数组放入第5个元素:0
			向数组放入第6个元素:0
			向数组放入第7个元素:0
			向数组放入第8个元素:0
			向数组放入第9个元素:0
			向数组放入第10个元素:0
			向数组放入第11个元素:0
			向数组放入第12个元素:0
			向数组放入第13个元素:0
			向数组放入第14个元素:0
			向数组放入第15个元素:0
			向数组放入第16个元素:0
			向数组放入第17个元素:0
			向数组放入第18个元素:0
			向数组放入第19个元素:0
			向数组放入第20个元素:0
			从数组取出第19个元素:0
			从数组取出第18个元素:0
			从数组取出第17个元素:0
			从数组取出第16个元素:0
			从数组取出第15个元素:0
			从数组取出第14个元素:0
			从数组取出第13个元素:0
			从数组取出第12个元素:0
			从数组取出第11个元素:0
			从数组取出第10个元素:0
			从数组取出第9个元素:0
			从数组取出第8个元素:0
			从数组取出第7个元素:0
			从数组取出第6个元素:0
			从数组取出第5个元素:0
			从数组取出第4个元素:0
			从数组取出第3个元素:0
			从数组取出第2个元素:0
			从数组取出第1个元素:0
			从数组取出第0个元素:0
			向数组放入第1个元素:0
			向数组放入第2个元素:0
			向数组放入第3个元素:0
			向数组放入第4个元素:0
			向数组放入第5个元素:0
*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值