线程

线程:

	java程序属于抢占式调度,那个线程的优先级高,那个线程先执行;同一优先级,随机选择一个
获取线程名称: getName()	currentThread() 当前线程的名称
	Thread.currentThread().getName()
	Runnable 的实现类中,没有getName方法

设置线程名称:

	1.使用Thread类中的方法setName(名字)改变线程名称,使之与参数相同
	2.创建一个带参数的构造方法,参数传递线程名称;调用父类的带参构造方法,把线程名称传递给父类,让父类給子线程起一个名字

线程优先级

	1、线程谁先运行谁后运行的级别
	2、Thread类中的setPriority设定优先级
	3、setPriority(int status)
	 	Status:从1-10,数字越大,优先级越高,越提前执行
	4、三个常量:
	 	MAX_PRIORITY 	10
	 	MIN_PRIORITY 	1
	 	NORM_PRIORITY 	5 	 	默认的优先级

创建多线程程序

创建多线程程序的第一种方式:创建Thread类的子类
	java.lang.Thread类,我们想要实现多线程程序,就必须继承Thread类
	实现步骤:
		1.创建一个Thread类的子类
		2.在Thread类的子类中重写Thread类中的run方法,设置线程任务
		3.创建Thread类的子类对象
		4.调用Thread类中的方法start方法,开启新的线程,执行run方法,当前线程(main)和另一个线程(创建的新的线程)并发的运行,多次启动一个线程是非法的,特别是当线程已经结束后,就不能在重新启动
		
创建多线程程序的第二种方式:实现 Runnable接口
	java.Lang.Runnable
	Runnable接口应给由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为一个run的无参数构造方法。
	java.lang.Thread类的构造方法
		Thread( Runnable target)分配新的 Thread对象
		Thread( Runnable target, string name)分配新的 Thread对象。
	实现步骤:
		1.建一个 Runnable接囗的实现类
		2.在实现类中重写 RunnabLe接口的run方法,设置线程任务
		3.创建一个 Runnable接口的实现类对象
		4.创建 Thread类对象,构造方法中传递 Runnable接口的实现类对象
		5.调用 Thread类中的 start方法,开启新的线程执行ru方法
		
创建多线程程序的第三种方式:使用匿名内部类方法
		new Thread() {
			@Override
			public void run() {
				for (int i = 0;i<10 ;i++) {
					System.out.println("thread: "+Thread.currentThread().getName());
				}
			}
		}.start();;
		
		Runnable r = new Runnable() {
			@Override
			public void run() {
				for (int i = 0;i<10 ;i++) {
					System.out.println("runnable: "+Thread.currentThread().getName());
				}
			}
		};
		new Thread(r).start();

		new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 0;i<10 ;i++) {
					System.out.println("简化runnable接口: "+Thread.currentThread().getName());
								}	
			}
		}).start();

解决线程安全问题的一种方案:使用同步代码块

	格式:
		synchronized(锁对象){
		可能会出现线程安全的代码(访问了共享数据的代码)
		}
		
	注意:
	1.通过代码块中的锁对象,可以使用任意的对象
	2.但必须保证多线程使用的锁对象是同一个
	3.锁对象作用
		把同步代码块锁住,只让一个线程在同步代码块中执行

	class RunnableImp2 implements Runnable {
		private int ticket = 10;
		Object obj = new Object();

		@Override
		public void run() {
			while(true) {
				synchronized (obj) {
					if (ticket > 0) {
						try {
							Thread.sleep(10);
							System.out.println(Thread.currentThread().getName()+"-->"+"正在卖第"+ticket+"票");
							ticket--;
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
				}
				}
				
		}
	  }
	}

解决线程安全问题的二种方案:使用同步方法

	使用步骤:
		1.把访问了共享数据的代码抽取出来,放到一个方法中
		2.在方法上添加synchronied修饰符
	格式:
		修饰符 synchronized 返回值类型 方法名(参数列表){
			可能会出现线程安全问题的代码(访问了共享数据的代码)
		}
		
	注意:
		同步方法也会把方法内部的代码锁住,只让一个线程执行
		同步方法的锁对象是谁?
			就是实现类对象 new RunnableImpl(),也就是this
			
	使用静态同步方法
		锁对象是谁?
		不能是this,this是创建对象之后产生的,静态方法优于对象,静态方法的锁对象是本类的class属性-->class文件对象(反射)

解决线程安全问题的三种方案:使用Lock锁

	java.util.concurrent.locks.Lock接口
	Lock实现提供了比使用synchronized 方法和语句获得更广泛的锁操作。
	Lock接口中的方法:
		void lock()获得锁
		void unlock()释放锁
	java.util.concurrent.Locks.ReentrantLock implements Lock接口
	使用步骤:
		1.在成员位置创见一个ReentrantLock对象
		2.在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁
		3.在可能会出现安全问题的代码后调用Lock接口中的方法unlock释放锁

	同步锁是谁?
		对于非静态的方法,同步锁就是this
		对于static方法,我们使用当前方法所在类的字节码对象(类名.class)

等待唤醒案例:线程之间的通信

	创建一个顾客线程:告知老板要的包子的种类和数量,调用wait方法,放弃cpu的执行,进入到WAITING状态(无限等待)
	创建一个老板线程:花5秒做包子,做好包子之后,调用notify方法,唤醒顾客吃包子
	注意:
		顾客和老板之间必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行
		同步使用的锁对象必须保证唯一
		只有锁对象才能调用wait和notify方法
	Object类中的方法
		void wait()
			在其他线程调用此对象的notify()方法或者 notifyAll()方法前,导致当前线程等待
		void notify()方法
			唤醒在此对象监视器等待的单个线程
			会继续执行wait()方法之后的代码
		notifyAll()方法
			唤醒所有的线程

	Object obj = new Object();
		
		new Thread() {
			@Override
			public void run() {
				synchronized (obj) {
					System.out.println("告知老板要的数量与种类");
					try {
						obj.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println("包子做好了,开吃");
				}
			}
		}.start();

		new Thread() {

			@Override
			public void run() {
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				synchronized (obj) {
					System.out.println("老板花了五秒做好了包子,告知顾客");
					obj.notify();
				}
			}
			
		}.start();

解决线程安全问题
		public class BaoZi {
			String pi;
			String xian;
			boolean flag = false;
		}

		public class BaoZiPu extends Thread{
			private BaoZi bz;

			public BaoZiPu(BaoZi bz) {
				this.bz = bz;
			}
			@Override
			public void run() {
				int count = 0;
				while(true) {
					synchronized (bz) {
						if (bz.flag == true) {
							try {
								bz.wait();
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
						
						if (count % 2 == 0) {
							bz.pi = "薄皮";
							bz.xian = "三鲜馅";
						}else {
							bz.pi = "冰皮";
							bz.xian = "牛肉大葱";
						}
						count++;
						System.out.println("包子铺正在生产包子"+bz.pi+bz.xian+"包子");
						
						try {
							Thread.sleep(3000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						bz.flag = true;
						bz.notify();
						System.out.println("包子铺生产好了"+bz.pi+bz.xian+"包子");
					}
					
				}
			}
		}

			public class BaoZiChiHuo extends Thread{
				private BaoZi bz;

			public BaoZiChiHuo(BaoZi bz) {
				this.bz = bz;
			}
			
			@Override
			public void run() {
				while(true) {
					synchronized (bz) {
						if (bz.flag == false) {
							try {
								bz.wait();
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
						System.out.println("吃货正在吃"+bz.pi+bz.xian+"包子");
						bz.flag = false;
						bz.notify();
						System.out.println("吃货已经吃完了"+bz.pi+bz.xian+"包子吃完了,包子铺开始生成包子");
						System.out.println("-----------------------");
					}
				}
			}
		}

		public class BaZiTest {
			public static void main(String[] args) {
				BaoZi bz = new BaoZi();
				new BaoZiPu(bz).start();
				new BaoZiChiHuo(bz).start();
				
			}

		}

线程池: JDK1.5之后提供的

	java.util.concurrent.Executors:线程池的工厂类,用来生成线程池
	Executors类中的静态方法
		static ExecutorService newFixedThreadpooL( int nthreads)
		static ExecutorService newSingleThreadPool(): 生成一个具有一条线程的线程池

		创建一个可重用固定线程数的线程池
			参数:int nthreads:创建线程池中包含的线程数量
			返回值:
				Executorservice接口,返回的是 Executorservice接口的实现类对象
				我们可以使用 Executorservice接口接收(面向接口编程)
				
	java.util.concurrent.Executorservice:线程池接口
		用来从线程池中获取线程,调用 start方法,执行线程任务
			submit( Runnable task)提交一个 Runnable任务用于执行
		关闭销毁线程池的方法
			1、shutDown()
 	 	 		终止线程池的提交功能,已经提交的会都执行完
 	 		2、List<Runnable> shutDownNow
 	  	 		关闭线程池,返回还没有执行的任务,已经在运行的就执行完

	线程池的使用步骤
		1.使用线程池的工厂类 Executors里边提供的静态方法 newFixedThreadpooL生产一个指定线程数量的线程池
		2.创建一个类实现 Runnable接口,重写run方法,设置线程任务
		3.调用 ExecutorServicel中的方法 submit,传递线程任务(实现类),开启线程,执行run方法
		4.调用 Executorservice中的方法 shutdown销毁线程池(不建议执行)
	例子:
		class RunbleImp implements Runnable {
			@Override
			public void run() {
				for (int j = 0; j < 5; j++) {
					System.out.println(Thread.currentThread().getName()+"  hello");
					}
				}
			}

		 ExecutorService es = Executors.newFixedThreadPool(2);
		 es.submit(new RunbleImp());
		 es.submit(new RunbleImp());

线程状态

	1. 状态类型
		1、新建态:线程对象刚创建
		2、就绪态:准备好了运行,只要调用了start方法的线程,都是就绪态
		3、运行态:cpu正在处理和操作的线程
		4、阻塞态:线程休眠、线程等待、等待同步锁、I/O的时候都是阻塞态
		5、死亡态:线程正常运行结束或者被人为终止
	2、专门的类型:
		Thread.State,是枚举类型,该类中的对象是有限个的,提前创建好的
	3、枚举项:
	 	NEW:新建态
	 	RUNNABLE:就绪态和运行态
	 	BLOCKED:等待同步锁的阻塞状态
	 	WAITING:等待其他线程唤醒的状态
	 	TIMED_WAITING:有时间限制的休眠状态
	 	TERMINATED:死亡态
	4、获取线程状态:
	 	Thread.State  getState()
	 	获取调用者线程的状态
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值