您的位置:首页 > 职场人生

黑马程序员 java 基础 毕向东 面向对象 多线程

2014-09-14 22:29 615 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

黑马程序员 java 基础 毕向东 面向对象 多线程

1线程介绍

* 线程是一个执行中的程序

* 每一个进程执行都有一个执行顺序,该顺序是一个执行路径

* 或者叫一个控制单元

*

* 线程 才是进程中独立的控制单元

* 线程在控制着进程的执行

* 一个进程中至少有一个线程

*

* java 虚拟机启动时会有一个进程叫做java.ext

* 该进程中至少有一个进程,负责执行

* 这个线程运行的代码存在于main方法中

* 该线程称为主线程

*

* 扩展:更详细是说

* jvm启动不止一个线程,还有垃圾回收机制的线程



2 线程实现 继承Thread

package ThreadH;
/*
 * 线程是一个执行中的程序
 * 每一个进程执行都有一个执行顺序,该顺序是一个执行路径
 * 或者叫一个控制单元
 * 
 * 线程 才是进程中独立的控制单元
 * 线程在控制着进程的执行
 * 一个进程中至少有一个线程
 * 
 * java 虚拟机启动时会有一个进程叫做java.ext
 * 该进程中至少有一个进程,负责执行
 * 这个线程运行的代码存在于main方法中
 * 该线程称为主线程
 * 
 * 扩展:更详细是说
 * jvm启动不止一个线程,还有垃圾回收机制的线程
 * 
 * 
 * 如何自定义线程呢
 * 通过对api查阅,java以及封装了线程这类事物的描述即Thread类
 * 继承重新run即可
 * 步骤:
 * 1:继承Thread 
 * 2;复写run方法
 * 			目的:将自定义的代码存储在run方法中,让线程运行
 * 3:调用线程的start方法;有俩个作用,1启动线程2调用run方法
 * 结果并不相同,而且main和新线程并不是同时执行,
 * CPU实际上在线程之间快速切换,cpu 执行到谁,谁运行
 * 给人看起来是在同时执行的
 * 我们可以形象的多线程的运行行为在互相抢夺CPU的执行权
 * 执行多长时间,CPU说了算
 * 
 * 为什么要覆盖run方法呢
 * Thread 类用于描述线程。
 * 该类就定义了一个功能,用于存储线程要运行的代码,该
 * 存储功能就是run方法
 * 也就是说  Thread 的run方法 用于存储线程要执行的代码
 * 问题来了:
 * */
public class ThreadDemo{
	public static void main(String args[]) {
		Demo d=new Demo();
		d.start();
		//开启线程并执行该线程的run方法
//		d.run();仅仅是对象的调用
		for(int i=0;i<100;i++)
			System.out.println("main run");
	}
}
class Demo extends Thread{
	public void run(){
		for(int i=0;i<100;i++)
			System.out.println("demo run");
	}
}


3 线程名字

package ThreadH;
/*
 * 线程都有自己默认的名字 
 *THread-编号  从零开始
 *static Thread currenThread()获取当前线程的对象
 *getName() 获取线程的名称
 *setName() 或者使用构造函数  设置名称*/
public class ThreadTestT{

	public static void main(String[] args) {
		TestT t=new TestT("t1");
		TestT t2=new TestT("t2");
		t.start();
		t2.start();
		for (int i = 0; i < 60; i++) {
			System.out.println("main run +"+i);
		}
	}

}
class TestT extends Thread{
//	private String name;
	public TestT(String name) {
		super(name);
//		this.name=name;
	}
	public void run() {
		for (int i = 0; i < 60; i++) {
//			System.out.println(name+"test run +"+i);
			System.out.println((Thread.currentThread()==this)+this.getName()+"test run +"+i);
		}
	}
}




4 卖票程序 中 体现Runnable 实现方式 and 实现线程同步 and 线程同步锁 this





package ThreadH;

/*需求:简单的卖票程序
 * 多个窗口卖票
 * 创建线程的第二中方式:
 * 1;定义类实现Runnable接口,
 * 2:覆盖Runnable接口中的run方法
 * 			将线程要运行的代码存放在run方法中
 * 
 * 3:通过Thread类建立线程对象
 * 4:将Runnable接口的子类对象作为实际参数传递给Thread类的构造函
 * 			why?因为自定义的 的run方法所属的对象是Runnable接口的子类对象
 * 			所以要让线程去指定对象的run方法,就必须明确该run方法所属对象
 * 5:调用Thread类的start方格,开启线程并执行Runnable中的run方法
 * 
 * 实现方式和继承方式的区别;
 *关键的部分:
 *避免了单继承的局限性
 *建议使用 的多线程实现方式
 *
 *区别:
 *继承Thread线程代码存放在Thread的子类run方法中
 *
 *实现Runnable 线程代码存放在接口子类的run方法
 *
 *
 *通过分析,发现打印出0  -1  -2  等错票
 *多线程的运行出现了安全问题
 *
 *问题产生的原因:
 *当多条语句在操作线程共享数据时,一个线程对多条语句只执行了一部分,还木有执行完,
 *另一个线程进入参与执行,导致共享数据 的错误
 *
 *解决办法:
 *对多条操作共享数据 的语句,只能让一个线程执行完,在执行过程中,
 *其他线程不可以参与执行
 *
 *java 对于多线程的安全问题提供了专业的解决方式
 *就是同步代码块
 *synchronized(对象){
 *		需要被同步的代码
 *}
 *
 *对象如同锁,持有锁的线程可以在同步中执行
 *没有持有锁 的线程即使获取CPU 的执行权,也进不去,因为没获取锁
 *火车上的卫生间------------经典同步
 *
 *使用同步的前提:
 *1:必须有两个或两个以上的线程
 *2:必须是多个线程使用同一个锁
 *必须保证同步中只有一个线程在运行
 *
 *好处:解决了多线程的安全问题
 *弊端:多个线程每一次都需要判断,消耗了资源,   
 *
 *
 **同步函数用的是哪个锁呢???
 *  --------this-----
 *  函数需要被对象调用,函数都有所属对象的引用
 *  所以同步函数使用的锁是this
 *  
 *  使用该程序进行验证:
 *  一个线程在同步代码块中
 *  一个线程在同步函数中
 *  都在执行卖票动作
 *  Thread-1shwo sale:0  出现错票
 * */
public class TicketThread {

	public static void main(String[] args) {
//		Ticket ticket1=new Ticket();
//		Ticket ticket2=new Ticket();
//		Ticket ticket3=new Ticket();
//		Ticket ticket4=new Ticket();
//		ticket1.start();
//		ticket2.start();
//		ticket3.start();
//		ticket4.start();
//		ticket1.start();
//		ticket1.start();
//		ticket1.start();
//		ticket1.start();

		Ticket ticket=new Ticket();
		//构造方法:解决Thread(Runnable runnable)
		Thread t1=new Thread(ticket);
		Thread t2=new Thread(ticket);
		Thread t3=new Thread(ticket);
		Thread t4=new Thread(ticket);
		t1.start();
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		ticket.flag=false;
		t2.start();
//		t3.start();
//		t4.start();
	}

}
//class Ticket extends Thread{
//	private static int tick=100;
//	public void run() {
//		while(true){
//			if(tick>0){
//				System.out.println(currentThread().getName()+"sale:"+tick--);
//			}
//		}
//	}
//}
class Ticket  implements Runnable{
	private static int tick=400;
	Object obj=new Object();
	boolean flag=true;
	public void run() {
		if(flag){
			while(true){
//				synchronized(obj){//同步代码块
				synchronized(this){//同步代码块
					if(tick>0){
						try {
							Thread.sleep(10);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						System.out.println(Thread.currentThread().getName()+"run sale:"+tick--);
					}
				}
				
			}
		}else{
			while(true)
					show();
		}
	}
	synchronized void show (){
		if(tick>0){
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"shwo sale:"+tick--);
	}

	}
}
//class Ticket  implements Runnable{
//	private static int tick=400;
//	Object obj=new Object();
//	public void run() {
//		while(true){
//			show();
//		}
//	}
//	synchronized void show (){
//		if(tick>0){
//			try {
//				Thread.sleep(10);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
//			System.out.println(Thread.currentThread().getName()+"sale:"+tick--);
//	}
//	}
//}6


5卖票程序中 静态代码块 同步

package ThreadH;

/*需求:简单的卖票程序
 * 多个窗口卖票
 * 创建线程的第二中方式:
 * 1;定义类实现Runnable接口,
 * 2:覆盖Runnable接口中的run方法
 * 			将线程要运行的代码存放在run方法中
 * 
 * 3:通过Thread类建立线程对象
 * 4:将Runnable接口的子类对象作为实际参数传递给Thread类的构造函
 * 			why?因为自定义的 的run方法所属的对象是Runnable接口的子类对象
 * 			所以要让线程去指定对象的run方法,就必须明确该run方法所属对象
 * 5:调用Thread类的start方格,开启线程并执行Runnable中的run方法
 * 
 * 实现方式和继承方式的区别;
 *关键的部分:
 *避免了单继承的局限性
 *建议使用 的多线程实现方式
 *
 *区别:
 *继承Thread线程代码存放在Thread的子类run方法中
 *
 *实现Runnable 线程代码存放在接口子类的run方法
 *
 *
 *通过分析,发现打印出0  -1  -2  等错票
 *多线程的运行出现了安全问题
 *
 *问题产生的原因:
 *当多条语句在操作线程共享数据时,一个线程对多条语句只执行了一部分,还木有执行完,
 *另一个线程进入参与执行,导致共享数据 的错误
 *
 *解决办法:
 *对多条操作共享数据 的语句,只能让一个线程执行完,在执行过程中,
 *其他线程不可以参与执行
 *
 *java 对于多线程的安全问题提供了专业的解决方式
 *就是同步代码块
 *synchronized(对象){
 *		需要被同步的代码
 *}
 *
 *对象如同锁,持有锁的线程可以在同步中执行
 *没有持有锁 的线程即使获取CPU 的执行权,也进不去,因为没获取锁
 *火车上的卫生间------------经典同步
 *
 *使用同步的前提:
 *1:必须有两个或两个以上的线程
 *2:必须是多个线程使用同一个锁
 *必须保证同步中只有一个线程在运行
 *
 *好处:解决了多线程的安全问题
 *弊端:多个线程每一次都需要判断,消耗了资源,   
 *
 *
 **同步函数用的是哪个锁呢???
 *  --------this-----
 *  函数需要被对象调用,函数都有所属对象的引用
 *  所以同步函数使用的锁是this
 *  
 *  使用该程序进行验证:
 *  一个线程在同步代码块中
 *  一个线程在同步函数中
 *  都在执行卖票动作
 *  Thread-1shwo sale:0  出现错票
 * */
public class StaticTicketThread {

	public static void main(String[] args) {
//		Ticket ticket1=new Ticket();
//		Ticket ticket2=new Ticket();
//		Ticket ticket3=new Ticket();
//		Ticket ticket4=new Ticket();
//		ticket1.start();
//		ticket2.start();
//		ticket3.start();
//		ticket4.start();
//		ticket1.start();
//		ticket1.start();
//		ticket1.start();
//		ticket1.start();

		TicketSta ticket=new TicketSta();
		//构造方法:解决Thread(Runnable runnable)
		Thread t1=new Thread(ticket);
		Thread t2=new Thread(ticket);
		Thread t3=new Thread(ticket);
		Thread t4=new Thread(ticket);
		t1.start();
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		ticket.flag=false;
		t2.start();
//		t3.start();
//		t4.start();
	}

}
//class Ticket extends Thread{
//	private static int tick=100;
//	public void run() {
//		while(true){
//			if(tick>0){
//				System.out.println(currentThread().getName()+"sale:"+tick--);
//			}
//		}
//	}
//}
class TicketSta  implements Runnable{
	private static int tick=400;
	Object obj=new Object();
	boolean flag=true;
	public void run() {
		if(flag){
			while(true){
//				synchronized(obj){//同步代码块
//				synchronized(this){//同步代码块
				synchronized(TicketSta.class){//同步代码块
					if(tick>0){
						try {
							Thread.sleep(10);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						System.out.println(Thread.currentThread().getName()+"run sale:"+tick--);
					}
				}
				
			}
		}else{
			while(true)
					show();
		}
	}
//	static synchronized void show (){
	
	//如果是静态方法,使用的锁不再是this,因为静态方法不可以定义this
	//类进入内存,生成对应类的字节码对象
	//静态进内存,内存中没有本类对象,但一定有该类对应的字节码文件对象
	//类名.class  该对象的类型是Class
	//静态的同步方法,使用的锁是该方法所在类的字节码文件对象,类名.class 在内存中唯一
     static synchronized void show (){
		if(tick>0){
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"shwo sale:"+tick--);
	}

	}
}
//class Ticket  implements Runnable{
//	private static int tick=400;
//	Object obj=new Object();
//	public void run() {
//		while(true){
//			show();
//		}
//	}
//	synchronized void show (){
//		if(tick>0){
//			try {
//				Thread.sleep(10);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
//			System.out.println(Thread.currentThread().getName()+"sale:"+tick--);
//	}
//	}
//}


6银行程序 模拟多线程 操作

package ThreadH;

import sun.launcher.resources.launcher;

/*
 *银行有一个金库
 *有两个储户,分别存300员,每次存100,存3次
 *目的:该程序是否有安全问题?
 *如果有,如何解决
 *如何找到问题:
 *1:明确哪些代码是多线程运行代码
 *for (int i = 0; i < 3; i++) {
			bank.add(100);
		}
 *2:明确共享数据         private int sum;
				  private Bank bank=new Bank();
 *3:明确多线程运行代码中是操作共享数据的
 *
		sum+=n;
		System.out.println("sum="+sum);
 *
 *
 *同步的两种表现形式
 *1:同步代码块  synchronized(Object o) {  同步代码}
 *2:同步函数  将 synchronized 作为函数的修饰符
 *
 *
 *同步函数用的是哪个锁呢???
 *  --------this-----
 *  函数需要被对象调用,函数都有所属对象的引用
 *  所以同步函数使用的锁是this
 * */
public class BankDemo {
	public static void main(String[] args) {
		Cus cus=new Cus();
		Thread thread1=new Thread(cus);
		Thread thread2=new Thread(cus);
		thread1.start();
		thread2.start();
	}

}
class Bank{
	private int sum;
//	public void  add(int n) { 
//		synchronized (this) {
//			sum+=n;
//			try {
//				Thread.sleep(10);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
//			System.out.println("sum="+sum);
//		}
//		
//	}
	public synchronized void  add(int n) { 
//		synchronized (this) {
			sum+=n;
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("sum="+sum);
//		}
		
	}
}
class Cus implements Runnable{
	private Bank bank=new Bank();
	public void run() {
		for (int i = 0; i < 3; i++) {
			bank.add(100);
		}
	}
	
}


7单例模式中多线程 的使用 饿汉式 懒汉式

package ThreadH;
/*
 * 单例设计模式
 * 
 * 1:饿汉式
 * 2:懒汉式
 * -------------------------------------------------------
 * 饿汉式:
 * class ClassA {
 *     private static final ClassA c=new ClassA();
 * 		private  ClassA(){
 *   	}
 *   	public static ClassA getInstance(){
 *   		return c;
 *   	}
 * }
 * 
 * -------------------------------------------------------
 * 懒汉式
 * class ClassA {
 *     private static  ClassA c=null;
 * 		private  ClassA(){
 *   	}
 *   	public static ClassA getInstance(){
 *   		if(c==null){
 *   			c=new ClassA();
 *   		为空才实例化对象,所以叫做懒懒
 *   		也教师延迟加载,对象被延迟了
 *   		}
 *   		return c;
 *   	}
 * }
 * 
 * 懒汉式与饿汉式的区别:
 * 
 * */
public class SingleDemo {
	public static void main(String[] args) {
	}
}
class Single {
     private static  Single c=null;
 		private  Single(){
   	}
   	public static  Single getInstance(){
//  public static synchronized Single getInstance(){
   		//虽然可以解决同步问题,但会低效
   		
   		//用双重判断可以提高效率
   		/*
   		 * 分析执行过程
   		 * Thread 1执行到if(c==null)为真,
   		 * 执行synchronized (Single.class) {}
   		 * 获取了锁,其他线程可以可以执行到该行之前,但会在此次等待
   		 * Thread 判断if(c==null) 为真,实例化 c
   		 * 执行完同步代码块后退出,其他线程进入同步代码块,
   		 * 执行if(c==null) 为假,退出
   		 *  当以后的线程在实例化时,第一行的if(c==null)判断不通过
   		 *  就不会再执行同步代码块
   		 *  
   		 *  在以后的实例化过程中提高了下效率
   		 *  
   		 *  最好是选择是使用饿汉式
   		 * */
   		if(c==null){
   			synchronized (Single.class) {
   				if(c==null){
   					c=new Single();
   					}
   	   	   		}  	
   	  		}
   	   	return c; 
   		}
   		
 }


8思索死锁

例子1

package ThreadH;

/*思索死锁
 * 例如筷子
 * 
 * 同步中嵌套同步
 * */
public class DeadLockTicketThread {

	public static void main(String[] args) {

		TicketDead ticket=new TicketDead();
		//构造方法:解决Thread(Runnable runnable)
		Thread t1=new Thread(ticket);
		Thread t2=new Thread(ticket);
		t1.start();
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		ticket.flag=false;
		t2.start();
	}

}

class TicketDead    implements Runnable{
	private static int tick=1000;
	Object obj=new Object();
	boolean flag=true;
	public void run() {
		if(flag){
			while(true){
				synchronized(obj){//同步代码块
					show();
				}
				
			}
		}else{
			while(true)
					show();
		}
	}
    synchronized void show (){
		synchronized(obj){//同步代码块
			if(tick>0){
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+"run sale:"+tick--);
			}
		}

	}
}
//}


例子2

package ThreadH;
public class DeadLockTest{
	public static void main(String args[]) {
		Thread thread1=new Thread(new TestDe(true));
		Thread thread2=new Thread(new TestDe(false));
		thread1.start();
		thread2.start();
	}
}
class TestDe implements Runnable {
	private boolean flag;
	public TestDe(boolean flag) {
		this.flag= flag;
	}
	@Override
	public void run() {
		if (flag) {
			while(true){
				synchronized (MyLock.locka) {
					System.out.println("if locka");
					synchronized (MyLock.lockb) {
						System.out.println("else lockb");
					}
				}
			}
			
		}else {
			while(true){
			synchronized (MyLock.lockb) {
				System.out.println("else lockb");
				synchronized (MyLock.locka) {
					System.out.println("else locka");
				}
			}
			}//while
			
		}
	}
}
class MyLock{
	static Object locka=new Object();
	static Object lockb=new Object();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: