Java线程

线程

=================================
/*
 * 
 * 		了解并发和并行
 * 		什么是线程,什么是进程。
 * 
 * 	多线程:
 * 		并发:两个或多个事件在同一时间段内发生,cpu交替执行,效率低
 * 		并行:两个或多个事件在同一时刻发生(同时发生),cpu同时执行,速度快。
 * 		
 * 		进程:任务管理器中进程			进入到内存的程序叫进程
 * 				硬盘永久存储ROM
 * 				内存:所有的应用程序都需要进入到内存中执行,临时存储RAM,进入到内存的程序叫进程
 * 		线程:是进程的执行单元
 * 				一个程序执行后至少有一个进程,一个进程可以包含多个线程
 * 				CPU中央处理器,对数据进行计算,指挥电脑软件和硬件干活。
 * 				4核心-->8线程-->同时执行8个线程,8个线程在多个任务之间高速切换,速度提高8倍
 * 		线程属于进程,是进程的中的一个执行单元。
 * 		cpu在多个进程之间高速切换,轮流执行多个线程,效率低。
 * 		多线程效率高,多个线程之间互不影响。
 * 
 * 		线程调度:
 * 			分时调度:轮流执行
 * 			抢占式调度:优先让优先级高的先执行。
 * 
 * 		主线程:
 * 			执行主方法(main)的线程
 * 		
 * 		单线程程序: java程序只有一个线程
 * 			执行从main方法开始,从上往下依次执行
 * 
 */
public class XianCheng {
	
	public static void main(String[] args) {
		//单线程程序,小强先执行,旺财在执行,从上往下,依次执行
		Person p1 = new Person("小强");
		p1.run();
		
		Person p2 = new Person("旺财");
		p2.run();
		
	}

}

---------------------------------------
	public class Person {

	private String name;

	public void run(){
		//定义循环
		for(int i = 0;i < 20; i++){
			System.out.println(name+"-->"+i);
		}
	}
	
	public Person() {
		super();
	}
	

	public Person(String name) {
		super();
		this.name = name;
	}


	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
}

---------------------------------------
public class MyThread extends Thread{

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

---------------------------------------
/*
 * java.long.Thread类描述线程的类,想要实现多线程,就必须继承Thread类
 * 		创建多线程程序的第一种方式,创建Thread类的子类
 * 				另一种方式,事项Runable接口。
 * 		
 * 		创建一个Thread类的子类
 * 		在Thread类中重写Thread类中的run方法,设置线程任务(开启线程)
 * 		创建Thread类的子类对象
 * 		调用Thread类中的start方法,开启新的线程,执行run方法
 * 			void start() 使该线程开始执行
 * 
 */
public class ThreadCls {

	public static void main(String[] args) {
		//多线程,每次抢到的资源时间都是不一样的,抢占资源,谁抢到就执行相应的代码	
		/*
		 * 因为MyThread这个类继承自了Thread,并重写了其中的run方法
		 * 那么这个类就是一个线程类。
		 * 		开启线程类,调用其中的start()方法。
		 */
		MyThread mt = new MyThread();
		//不能调用run方法
		mt.start();
		//
		new MyThread().start();//匿名调用
		for(int i = 0; i <20; i++){
			System.out.println("main"+i);
		}
	}
}

=========================================

/*
 * 	多线程第一种方式。
 * 		继承自Thread类。
 */
public class MyThread extends Thread{

	//
	public MyThread(){
		
	}

	//这个方法是给带参输的名称来使用的。
	 public MyThread(String name){ 
		  //把线程名称传递给父类,让父类给子线程起一个名称 super(name);
	 }
	 	
	//重写的run方法,调用start方法,执行这个run
	@Override
	public void run() {
		//获取线程名称
		System.out.println(Thread.currentThread().getName());
	}
}

--------------------------------------------------------------------
/*
 * 	设置线程的名称
 * 		使用Thread中的方法setName
 * 			void setName(String name)改变线程名称,,时之与参数name相同
 * 		创建一个带参数的构造方法,参数传递线程的名称,调用父类的带参构造方法,把现成的名称传递给父类
 * 	  让父类Thread给子线程起一个名字
 * 			Thread(String name) 分配新的Thread对象
 *
 */
public class MyThreadTest {

	public static void main(String[] args) {
		//开启
		MyThread mt = new MyThread();
		mt.setName("设置为小强");//本来获取的为Thrad-0
		mt.start();
		//开启
		new MyThread("设置为旺财").start();
	}
}

-----------------------------------------------
/*
 * Thread类中常用方法
 * 		获取线程名称1:
 * 			使用Thread类中的getName()
 * 				String getName() 返回该线程的名称
 * 		获取线程的名称2:
 * 			先获取当前正在执行的线程,使用线程中的方法getName()获取线程的名称
 * 				static Thread currentThread() 返回对当前正在执行的线程对象的应用
 * 			
 * 
 * 
 */
public class ThreadCls extends Thread{

	//重写run方法
	@Override
	public void run() {
		// 获取线程名称,直接getName()就是线程的名称。
		String name = getName();
		System.out.println(name);
		
		//获取线程名称
		Thread t = Thread.currentThread();
		System.out.println(t);//Thread[Thread-0,5,main]
		String name2 = t.getName();
		System.out.println(name2);
		
		//连式编程
		System.out.println(Thread.currentThread().getName());
		
	}
	
}

-------------------------------------------
/*
 * public static void sleep(Long millis):
 * 		静态的方法可以通过类名直接调用。
 * 		使当前线程以指定的毫秒暂停(暂时停止执行),毫秒结束后,线程继续执行
 * 		
 * 
 */
public class ThreadSleep {

	public static void main(String[] args) {
		//模拟秒表
		for(int i = 0; i <= 60; i++){
			System.out.println(i);
			//使用Thread中的静态的方法,类名直接调用,睡眠1秒钟
			try {
				//类名直接调用
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

------------------------------------------
/*
 * 	线程的名称:
 * 		主线程:main
 * 		新线程:Thread-0,Thread-1,Thread-2
 * 
 * 	设置线程的名称
 * 		使用Thread中的方法setName
 * 			void setName(String name)改变线程名称,,时之与参数name相同
 * 		创建一个带参数的构造方法,参数传递线程的名称,调用父类的带参构造方法,把现成的名称传递给父类
 * 	  让父类Thread给子线程起一个名字
 * 			Thread(String name) 分配新的Thread对象
 * 
 */
public class ThreadTest {

	public static void main(String[] args) {
		//创建子类对象
		ThreadCls mt = new ThreadCls();
		//调用start,开启新的线程
		mt.start();
		new ThreadCls().start();
		new ThreadCls().start();
		//主线程
		System.out.println(Thread.currentThread().getName());
	}
}

====================================

Ranable

===================================

/*
 * java.long.Runnable;
 * 		将类声明为Runable接口的实现类,重写run方法
 * 		它里面没有start对象,需要创建实现类对象Thread
 * 		
 * 		创建多线程程序的第二种方法,实现Runable接口
 * 	java.lang.Thread类的构造方法
 * 		Thread(Runable target) 分配新的Thread对象
 * 		Thread(Runable target,String name) 分配新的对象
 * 		
 * 		创建一个Runable接口的实现类
 * 		在实现类中重写Runable接口的run方法,设置线程任务	
 * 		创建一个Runable接口的实现类对象
 * 		创建Thread类对象,构造方法之中传递Runable接口的实现类对象
 * 		调用Thread类中的start方法,开启新的线程执行run方法	
 * 
 * 
 * 	继承Thread类和实现Runable接口的区别:
 * 		实现Runable接口创建多线程的好处,避免了单继承的局限性,
 * 			一个类只能继承一个类,类继承了Thread就不能再继承其他类了。
 * 			实现Runable接口还可以继承其他的类,实现其它接口
 * 			增强了程序的扩展性,降低了程序的耦合性  
 * 				设置线程任务和开启线程进行分离
 * 			实现类中重写了run方法,用来设置线程任务,创建Thread类对象,调用start方法,用来开启线程
 * 					推荐实现Runable接口。
 * 
 * 
 */
public class RunableCls {

	public static void main(String[] args) {
		//实现Runable接口,调用的时候还得new Thread(传递runable接口对象);
		RunableImpl run = new RunableImpl();
		//构造方法中调用RunableImpl的实现类
		Thread t = new Thread(run);
		//匿名对象实现人Runable接口。
//		Thread t = new Thread(new RunableImpl());
		//开启
		t.setName("抖音");//自定义线程名称
		t.start();
		//main方法的线程
		for (int i = 0; i < 20; i++) {
			
			System.out.println(Thread.currentThread().getName()+"-->"+i);
		}
	}
	
}

------------------------------------------------
/*
 *	 匿名内部类实现线程的创建:
 * 		匿名:没有名字
 *  	内部类:写在其他类内部的类
 *  
 *  	匿名内部类:简化代码
 * 		new 父类/接口(){
 * 			重写父类/接口中的方法
 * 		}
 * 
 */
public class InnerClassThread {

	public static void main(String[] args) {
		//线程的父类是Thread
		new Thread(){
			//重写run方法,设置线程任务
			@Override
			public void run() {
				for (int i = 0; i < 20; i++) {
					System.out.println(Thread.currentThread().getName()+"-->"+"黑马");
				}
			}
			
		}.start();
		
		//线程的接口Runbable
		//RunbableImpl
		//Runnable r = new RunbableImpl();接口等于实现类-->多态
		Runnable r = new Runnable() {
			@Override
			public void run() {
				for (int i = 0; i < 20; i++) {
					System.out.println(Thread.currentThread().getName()+"-->"+"程序员");
				}
			}
				
		};
		new Thread(r).start();
		
		//简化接口的方式,直接把r传进来
		new Thread( new Runnable() {
			@Override
			public void run() {
				for (int i = 0; i < 20; i++) {
					System.out.println(Thread.currentThread().getName()+"-->"+"传智播客");
				}
			}
				
		}).start();
	}
}

------------------------------------------
public class RunableImpl implements Runnable{

	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			System.out.println(Thread.currentThread().getName()+"-->"+i);
		}
		
	}

}

==============================

Lock

==============================

/*
 * Lock接口:
 * 		lock():获取锁
 * 		unlock():施放锁
 * 	
 * 	线程状态:
 * 		新建   运行   阻塞  死亡  休眠  永久等待
 * 
 */
public class LockCls {

}

------------------------------------
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/*
 *	 实现卖票案例:
 * 		第三种解决方案
 * 		java.util.concurrent.locks.Lock接口
 * 		Lock接口中的方法:
 * 			void Lock():获取锁
 * 			void unLock():释放锁
 * 
 * 		使用步骤:
 * 			java.util.concurrent.Locks.ReentrantLock implements Lock接口
 * 			在成员位置创建一个实现类,ReentrantLock对象
 * 			在可能出现代安全问题的代码前调用Lock接口,调用lock中的方法中获取锁
 * 			在可能出现安全问题的代码后调用Lock接口的方法unLock释放锁
 * 
 * 		创建锁是关键		 new ReentrantLock();
 * 			锁对象和同步的概念不一样
 * 			同步是同步,锁对象是锁对象
 * 				锁对象在可能出现代码安全问题前面调用锁
 * 				锁对象在可能出现代码安全问题后面释放锁
 * 
 * 				
 */
public class RunableImpl implements Runnable {

	//定义多个线程共享的数据
	private int ticket = 100;
	//创建实现类。
	Lock l = new ReentrantLock();
	
/*	//设置线程任务卖票
	@Override
	public void run() {
		//使用死循环让代码重复执行
		while(true){
			//在可能出现安全问题的代码前调用锁
			l.lock();
		//先判断票是否存在
		if(ticket > 0){
			try {
				//让程序睡眠,当线程休眠的时候三个线程可能有两个多个就进来执行,让问题更清晰的出现
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"-->正在卖第:"+ticket+"张票");
			ticket--;
		}
		//在可能出现安全问题的代码后施放锁
		l.unlock();
	  }
	}*/
	
	
	
	//设置线程任务卖票,无论程序是否异常都会把锁施放,提高程序的效率
	@Override
	public void run() {
		//使用死循环让代码重复执行
		while(true){
			//在可能出现安全问题的代码前调用锁
			l.lock();
			//先判断票是否存在
			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();
				}finally{
					//在可能出现安全问题的代码后施放锁
					l.unlock();
				}
			}
		}
	}
}

------------------------------------------
/*
 * 	线程安全问题:
 * 	使用线程同步技术解决线程问题
 */
public class ThreadSafe {

	public static void main(String[] args) {
		//创建一个实现类才能共享
		RunableImpl run = new RunableImpl();
		Thread t0 = new Thread(run);
		Thread t1 = new Thread(run);
		Thread t2 = new Thread(run);
		//调用start开启多线程
		t0.start();
		t1.start();
		t2.start();
	}
}

-------------------------------
/*
 * 	简单的线程通信:
 * 	等待和唤醒
 * 		线程之间的通信
 * 		创建一个消费者线程,告知老板需要购买的产品,调用wait,放弃cpu的执行,进入等待状态
 * 		创建一个来办线程,花5秒时间生产商品,,生产好之后唤醒顾客
 * 		
 * 		注意事项:
 * 			顾客和老版线程必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行
 * 			同步锁对象必须保证是唯一的
 *			
 *		Object类中的方法
 *			等待和唤醒。
 *				需要创建Object类的对象。
 *			void wait()
 *			void notify()
 *
 */
public class WaitAndNotify {

	public static void main(String[] args) {
		//创建等待和唤醒的对象。
		Object obj = new Object();
		//创建一个顾客线程消费者
		new Thread(){
			public void run() {
				//一直等着
				while(true){
				//保证等待和唤醒的线程只能有一个执行,需要使用同步技术
				synchronized (obj) {
					System.out.println("告知老板需要的包子的数量");
					try {
						//父类的run方法没有抛异常只能try-catch
						//走到这一步就开始,下面的代码不会执行,因为他在一直等待中,直到obj这个对象被唤醒
						obj.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					//老板唤醒之后继续执行wait之后的代码
					System.out.println("开吃");
					System.out.println("---------------------------------");
					}
				}
			}
		}.start();;
		
		//创建一个老板的线程
		new Thread(){
			//花5秒时间做包子
			@Override
			public void run() {
				while(true){
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				synchronized (obj) {
					System.out.println("老板5秒钟之后做好包子,告知顾客");
					//唤醒
					obj.notify();
				}
			  }
			}
		}.start();;
	}
}

------------------------------------------
/*
 * 	进入TimeWaiting(计时等待)
 * 		使用sleep(Long m)方法,在毫秒值结束之后,进入到可运行或阻塞状态
 * 		使用wait(Long m)方法,wait方法在毫秒结束之后,还没有被唤醒,就会自
 * 	动醒来,进入到可运行或者阻塞状态
 * 		唤醒的方法:
 * 			void notify():唤醒单个
 * 			void notifyAll():唤醒所有线程
 * 	synchronized
 * 		保证等待和唤醒的线程只能有一个执行,需要使用同步技术
 * 		
 */
public class WaitTimeAndNotify {

	public static void main(String[] args) {
		//创建锁对象
				Object obj = new Object();
				//创建一个顾客线程消费者
				new Thread(){
					public void run() {//一直等着
						while(true){
						//保证等待和唤醒的线程只能有一个执行,需要使用同步技术
						synchronized (obj) {
							System.out.println("顾客一告知老板需要的包子的数量");
							try {
								//父类的run方法没有抛异常只能try-catch
								obj.wait(5000);
							} catch (InterruptedException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
							//老板唤醒之后继续执行wait之后的代码
							System.out.println("1开吃");
							System.out.println("---------------------------------");
							}}}
				}.start();;
				//创建一个顾客线程消费者
				new Thread(){
					public void run() {
						//一直等着
						while(true){
					//保证等待和唤醒的线程只能有一个执行,需要使用同步技术
							synchronized (obj) {
					System.out.println("顾客二告知老板需要的包子的数量");
								try {
					//父类的run方法没有抛异常只能try-catch
					//这个唤醒是随机的,所以顾客一告知也可能栓性顾客二来吃
									obj.wait(5000);
								} catch (InterruptedException e) {
					// TODO Auto-generated catch block
									e.printStackTrace();
								}
								//老板唤醒之后继续执行wait之后的代码
								System.out.println("2开吃");
								System.out.println("---------");
							}}}
				}.start();
				//创建一个老板的线程
				new Thread(){
					//花5秒时间做包子
					@Override
					public void run() {
						while(true){
						try {
							Thread.sleep(5000);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						synchronized (obj) {
			System.out.println("老板5秒钟之后做好包子,告知顾客");
							//唤醒
//				obj.notify();//此时只能随机的唤醒一个顾客
							obj.notifyAll();//唤醒所有等待的线程
						}}}
				}.start();;
				
	}
}

=========================

线程安全问题

===========================

/*
 * 	线程安全问题:
 * 		模拟买票案例
 * 		创建三个线程,对共享数据操作
 * 		出现重复票和-1的问题
 * 
 * 	三个线程一起抢夺cpu的执行权,可能抢夺到同一资源,并且都执行
 * 		
 * 	使用线程同步技术解决线程问题
 */
public class ThreadSafe {

	public static void main(String[] args) {
		//创建一个实现类才能共享
		RunableImpl run = new RunableImpl();
		Thread t0 = new Thread(run);
		Thread t1 = new Thread(run);
		Thread t2 = new Thread(run);
		//调用start开启多线程,可依发现这三个人都卖掉了100张票,总共卖掉300张。
		t0.start();
		t1.start();
		t2.start();
	}
}

-----------------------------
/*
 * 	实现卖票案例:
 * 
 */
public class RunableImpl implements Runnable {

	//定义多个线程共享的数据
	private int ticket = 100;
	//设置线程任务卖票
	@Override
	public void run() {
		//使用死循环让代码重复执行
		while(true){
		//先判断票是否存在
		if(ticket > 0){
			try {
				//让程序睡眠,当线程休眠的时候三个线程可能有两个多个就进来执行,让问题更清晰的出现
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"-->正在卖第:"+ticket+"张票");
			ticket--;
		}
	  }
	}
}

--------------------------------
/*
 * 	使用同步方法解决:
 * 		把访问了共享数据的代码抽取出来,放到一个方法当中
 * 		在方法上添加一修饰符
 * 	格式:
 * 		修饰符  synchronized 返回值类型 方法名(参数列表){
 * 			可能产生问题的代码(访问共享数据的代码)
 * 		}
 * 
 * 		定义一个同步方法,同步对象也会把代码锁住,只让一个线程执行
 * 		同步方法锁对象 实现类对象 new RunnableImpl(),也就是this.
 * 
 */
//当这个类实现这个接口的时候,这就是一个多线程的类。
public class RunableImplDemoSyn implements Runnable {

	//定义多个线程共享的数据
	private int ticket = 100;
	//设置线程任务卖票,run方法中重写要实现的功能,在其中调用payTicket方法,这个方法被synchronize进行修饰,
	//就是一个同步方法,只让一个线程执行
	@Override
	public void run() {
		System.out.println(this);
		//使用死循环让代码重复执行
		while(true){
		//调用一下
			payTicket();
	  }
	}
	//定义一个同步方法,也可生声明为static,ticket变为static即可
	//静态方法优先于对象,锁对象是是本类的class对象
	public synchronized void payTicket(){
		if(ticket > 0){
			try {
				//让程序睡眠,当线程休眠的时候三个线程可能有两个多个就进来执行,让问题更清晰的出现
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"-->正在卖第:"+ticket+"张票");
			ticket--;
		}
	}

}

---------------------------------
/*
 * 	实现卖票案例:
 * 		解决线程安全问题
 * 		使用同步代码块
 * 		格式:
 * 			synchronized(锁对象){
 * 				可能出现线程安全问题的代码(访问共享数据数据的代码)
 * 			}
 * 		同步代码块中的锁对象,可以使用任意的对象
 * 		但是必须保证多个线程使用的锁对象是同一个
 * 		锁对象的作用:把同步代码块锁住,只让一个线程在同步代码块中执行
 * 
 * 		同步技术原理:
 * 			使用锁对象,同步锁,也叫对象锁,对象监视器
 * 			三个线程一起抢夺CPU的执行权,谁抢到谁执行
 * 			遇到同步代码块,这时会检查同步代码块是否有锁对象,发现有就会获取锁对象,进入到同步中执行
 * 			第二个对象进入,如果没有,就会进入阻塞状态直到第一个对象归还锁对象
 * 		 同步中的线程,没有执行完不会释放锁对象,同步外线程没有锁进不去同步
 * 			程序频繁的判断锁,释放锁,会降低程序的效率。
 * 
 */
public class RunableImplTongBu implements Runnable {

	//定义多个线程共享的数据
	private int ticket = 100;
	//创建一个锁对象
	Object obj = new Object();
	//设置线程任务卖票
	@Override
	public void run() {
		//使用死循环让代码重复执行
		while(true){
		synchronized (obj) {
			//先判断票是否存在
			if(ticket > 0){
				try {
					//让程序睡眠,当线程休眠的时候三个线程可能有两个多个就进来执行,让问题更清晰的出现
					Thread.sleep(10);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+"-->正在卖第:"+ticket+"张票");
				ticket--;
			}
		}
	  }
	}
}

---------------------------------
/*
 * 使用线程同步技术解决线程问题
 */
public class ThreadSafeDemoSyn {

	public static void main(String[] args) {
		//创建一个实现类才能共享
		RunableImplDemoSyn run = new RunableImplDemoSyn();
		System.out.println(run);
		Thread t0 = new Thread(run);
		Thread t1 = new Thread(run);
		Thread t2 = new Thread(run);
		//调用start开启多线程
		t0.start();
		t1.start();
		t2.start();
	}
}

---------------------------------
/*
 * 	使用线程同步技术解决线程问题
 * 
 */
public class ThreadSafeTongBu {

	public static void main(String[] args) {
		//创建一个实现类才能共享
		RunableImplTongBu run = new RunableImplTongBu();
		Thread t0 = new Thread(run);
		Thread t1 = new Thread(run);
		Thread t2 = new Thread(run);
		//调用start开启多线程
		t0.start();
		t1.start();
		t2.start();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值