黑马程序员——JAVA之多线程

------- http://www.itheima.com" target="blank">android培训http://www.itheima.com"target="blank">java培训、期待与您交流!

 

基础知识概述

 

<span style="font-family:Microsoft YaHei;font-size:14px;">package com.hyx;


 /* 一、关于进程和线程
 * 进程:正在运行的程序,是系统进行资源分配和调用的独立单位;每一个进程都有它自己的内存空间和系统资源。
 * 线程:是进程中的单个顺序控制流,是一条执行路径;一个进程如果只有一条执行路径,则称为单线程程序;一个进程如果有多条执行路径,则称为多线程程序。
 * 
 * 二、关于并行和开发
 * 并行:前者是逻辑上同时发生,指在某一个时间内同时运行多个程序。
 * 并发:后者是物理上同时发生,指在某一个时间点同时运行多个程序。
 * 
 * 三、Java程序的运行原理:
 * 	    由java命令启动JVM,JVM启动就相当于启动了一个进程;接着由该进程创建了一个主线程去调用main方法。
 * 
 *   Java虚拟机的启动也是多线程的:至少有两个,主线程和垃圾回收线程。启动垃圾回收线程的原因是为了防止内存溢出。
 * 
 * 四、实现多线程的三种方式:
 * 	  1.继承Thread类:
 * 			步骤:自定义类继承Thread类--->自定义类重写run()方法--->创建自定义类对象--->调用start()方法启动线程
 * 	  2.实现Runnable
 * 			步骤:自定义类是想Runnable接口--->自定义类重写run()方法--->创建自定义类对象;创建Thread类对象并将自定
 * 		义类对象作为实参传入Thread类中--->调用Thread类的start()方法启动线程new Thread(new MyThread()).start();
 *    3.实现Callable接口(JDK5)
 *    
 * 五、该类为什么要重写run()方法呢?
 * 	        不是类中所有的代码都需要被线程执行的;为了区分哪些代码能够被执行,java提供了Thread类中的run()方法用来包含那些被线程执行的代码。
 * 		
 * 六、同步有三种方式:1.同步代码块    2.同步方法  3.Lock锁
 * 
 * 七、面试题:run()与start()的区别?
 * 	   run()方法:仅仅是封装被线程执行的代码,直接调用是普通方法;
 * 	   start()方法:首先启动了线程,然后再由JVM去调用该线程的run()方法。
 * 
 * 八、线程常用方法:
 * 		1.线程名称:
 *			setName(String n):设置线程名称:
 *		    getName():获取线程名称;
 *		2.线程优先级:低-->高:1--10。默认:5
 *			setPriority(int n):设置优先级。如果不在1--10的范围内,则抛出异常;
 *			getPriority():获取线程的优先级;
 *		3.线程休眠:
 *			sleep(int n):静态方法。单位:毫秒;
 *		4.线程的加入:
 *			join():普通方法。其它线程会等待此线程执行完毕再执行;
 *		5.线程的礼让:
 *			yield():静态方法。退回到"就绪"状态。很可能会被操作系统再次分配运行;
 *		6.守护线程:
 *			setDaemon(boolean n):如果true,则为"守护线程"。当主线程结束时,守护线程也会跟着结束(但不会立即结束,会有个小缓冲)
 *		7.线程的中断:
 *			stop():不建议使用。
 *			interrupt():在线程内部,当处于以下三种情况:
 *					Object-->wait():
 *					Thread-->join():
 *					Thread-->sleep():
 *				             会触发一个异常的产生;
 * 九、线程的生命周期
 * 		创建--》就绪--》运行--》死亡;
 *		当一个线程start()后,线程不会被立即执行,其出于就绪状态,等待CPU分配其运行空间。
 * 十、同步
 * 		1.同步代码块:synchronized(被锁的对象){}
 * 		2.同步方法:public synchronized void show(){}
 * 			A、静态方法内,可以包含“同步代码块”,但被锁的对象不能使用this,一般是使用此类的Class对象
 *     		B、静态方法,可以被声明为“同步方法”。
 *      3.JDK5的Lock锁:
 *      Lock l = ...;
 *      l.lock();	//加锁
 *      try{//同步的代码
 *      }finally{
 *      l.unlock();//释放锁
 *      }
 *  十一、设计模式:1.简单工厂模式:  2.工厂方法模式  3.单例模式:1).饿汉式;2).懒汉式;
 *  十二、线程池:JDK5
 *      1.获取线程池:
 *        Executors中的静态方法:
 *        public static ExecutorService newCachedThreadPool()
 *        public static ExecutorService newFixedThreadPool(int nThreads)
 *        public static ExecutorService newSingleThreadExecutor()
 *      2.ExecutorService中的方法:
 *        Future<?> submit(Runnable task):执行线程,并获取返回值;
 *        <T> Future<T> submit(Callable<T> task)
 *     
 */
 
public class MyThread {

}
</span>


 

 

通过代码演示加强认知

  一、线程实现方式一:继承Thread类

<span style="font-family:Microsoft YaHei;font-size:14px;">
class Test{
	public static void main(String[] args){
		//创建线程对象
		Thread1 t = new Thread1();
		Thread1 t1 = new Thread1();
//		Thread1 t2 = new Thread1();
		//设置线程名称
		t.setName("轻水");
		t1.setName("青璃");
		// t2.setName("琉夏");
		//调用start()方法启动线程
		t.start();
		t1.start();
//		t2.start();
		//主方法中的程序
		for (int i = 0; i < 100; i++) {
			System.out.println(i);
		}
	}
}</span>


 

<span style="font-family:Microsoft YaHei;font-size:14px;">package cn.itcast;

public class Thread1 extends Thread {
	public void run() {
		for (int i = 0; i < 50; i++) {
			System.out.println(this.getName()+"	["+i+"]");
			try {
</span>
<span style="font-family:Microsoft YaHei;font-size:14px;">				//休眠一秒钟</span>
<span style="font-family:Microsoft YaHei;font-size:14px;">				Thread1.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}
	
}
</span>


 

 

二、多线程实现方式二

 

 

<span style="font-family:Microsoft YaHei;font-size:14px;">/*
 * 线程实现Runnable(建议使用)
 * 1.自定义实现Runnable接口;
 * 2.重写run()方法;
 * 3.启动线程:
 * 		1).实例化我们自定义类的对象;
 * 		2).实例化一个Thread对象,将我们的自定义对象作为参数传递给Thread的构造方法;
 * 		3).调用Thread对象的start()方法启动线程
 * 
 * class Thread{
 * 		private Runnable target = null;
 * 		public Thread(){
 * 		}
 * 		public Thread(Runnable runnable){
 * 			this.target = runnable;
 * 		}
 * 		public void start(){
 * 			if(this.target == null){
 * 				run();
 * 			}else{
 * 				target.run();
 * 			}
 * 		}
 * 		public void run(){
 * 			System.out.println("a");
 * 		}
 * }
 */
public class Demo {
	public static void main(String[] args) {
		MyRunnable myRun = new MyRunnable();
		Thread t = new Thread(myRun);
		t.start();
		for(int k = 0 ;k < 100 ; k++){
			System.out.println("k = " + k);
		}
	}
}
</span>

 

<span style="font-family:Microsoft YaHei;font-size:14px;">
public class MyRunnable implements Runnable {

	@Override
	public void run() {
		for(int i = 0;i < 100 ; i++){
			System.out.println("i = " + i);
		}
	}

}
</span>


 

三、使用同步解决并发访问的问题

 

 

<span style="font-family:Microsoft YaHei;font-size:14px;">/*
 * 使用同步解决并发访问的问题:
 * 
 * 1.在共享资源上(一般是一些方法)使用关键字:synchronized
 * 2.作用:当一个线程访问时,其它线程全部列队等待;这种机制保证了这个方法在同一时刻
 *       只能被一个线程访问;
 * 3.synchronized语法:
 * 		1.同步代码块:
 * 			synchronized(被锁的对象){
 * 				//同步代码
 * 			}
 * 	 注:被锁的对象:当一个线程访问此段代码时,会将这个对象中所有的"同步代码块"和"同步方法"加锁,
 *     也就意味着,一个线程访问一段同步代码块,其它线程不能访问"被锁对象"的其它"同步代码块"和"同步方法";
 */
public class Demo {
	public static void main(String[] args) {
		//1.实例化一个票池;
		Tickets tic = new Tickets();
		//2.实例化三个线程,模拟三个窗口售票
		MyThread t1 = new MyThread(tic);
		MyThread t2 = new MyThread(tic);
		MyThread t3 = new MyThread(tic);
		//3.设置线程名称
		t1.setName("窗口1");
		t2.setName("窗口2");
		t3.setName("窗口3");
		
		//4.启动线程
		t1.start();
		t2.start();
		t3.start();
		
		
	}
}
</span>


 

 
<span style="font-family:Microsoft YaHei;font-size:14px;">
import java.util.TreeSet;

public class MyThread extends Thread{
	private Tickets tic;
	private int count;
	private TreeSet<Integer> tree = new TreeSet<>();
	public MyThread(Tickets t){
		this.tic = t;
	};
	public void run() {
		while(true){
			int t = this.tic.getTicket();
			if(t > 0){
			//	System.out.println(this.getName() + " 抢到票:" + t);
				tree.add(t);
			}else{
			//	System.out.println("没票了,不抢了");
				break;
			}
		}
		System.out.println(this.getName() + " 共抢到 : " + tree.size() + " 张票,明细:" + tree);
		
	}
}
</span>


 

  

<span style="font-family:Microsoft YaHei;font-size:14px;">
public class Tickets {
	private int ticketNo = 100;
	public int getTicket(){//窗口1
		synchronized (this) {
			if(this.ticketNo > 0){//窗口1
				return this.ticketNo--;//窗口1
			}else{
				return 0;
			}
		}
	}
	
}
</span>


 

 

 

四、单例设计模式面试题

 

 

<span style="font-family:Microsoft YaHei;font-size:14px;">/*
	单例设计:饿汉式、懒汉式
	重点:懒汉式  
	面试题:1.问:懒汉式和饿汉式有什么不同?
			     答;懒汉式的特点在于实例的延迟加载。
			 2.问:懒汉式的延迟加载有没有问题?
				答:有,如果多线程访问时会出现安全问题。
			3.问:怎么解决?
				答:可以通过加同步来解决。
			4.问:加同步的方式?
				答:用同步代码块可以,但效率有点低;可以用
				双重判断的方式提高效率。
			5.加同步的时候使用的锁是:该类所属的字节码文件
*/


//饿汉式
class Single
{
	private static final Single s = new Single();
	private Single(){
	
	}
	public static Single getInstance(){
		return s;
	}
}


//懒汉式
class Single 
{
	private static Single s =null;
	private Single(){
	
	}
	public static Single getInstance(){
		if (s==null){
			synchronized(Single.class){
				if(s==null)
				s = new Single();
			}
		}
		return s;
	}
}</span>


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值