Day16----多线程

多线程

并行与并发

  • 并发、两个或多个时间同一时间段内发生----交替执行,段时间
  • 并行、两个或多个时间同一时刻内发生----同时发生
    线程与进程
  • 进入到内存的程序叫进程
  • 线程属于进程,是进程中的一个执行单元,负责程序的执行
  • 主线程:执行主方法,main方法的路径
    创建多线程
    ①创建Thread的子类
  • 创建一个Thread的子类
  • 在Thread大的子类中重写Run方法,设置线程任务
  • 此案件Thread的子类对象
  • 调用Thread类中的方法Strat方法,开启新的线程,执行run方法
public class Method1Thread extends Thread{
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			System.out.println(i+"i");
		}
	}
}

package java16;

public class Method1ThreadMain {

	public static void main(String[] args) {
		Method1Thread m=new Method1Thread();
		m.start();
		
		for(int i=0;i<20;i++) {
			System.out.println("main"+i);
		}
	}

}

②实现Runnable接口

  • 创建一个Runnable接口的实现类
  • 实现类中重写Runnable接口的run方法,设置线程任务
  • 创建一个Runnable类的实现对象
  • 创建Thread类对象,构造方法中传递Runnable接口实现类对象
  • 调用Thread类中的Start方法,开始心线程执行run方法
package java16;

public class RunnableImple implements Runnable{//创建一个Runnable接口的实现类
	@Override
	public void run() {//实现类中重写Runnable接口的run方法,设置线程任务
		for (int i = 0; i < 20; i++) {
			System.out.println(Thread.currentThread().getName()+"     "+i);
		}
	}
}

package java16;

public class RunnableMain {

	public static void main(String[] args) {
		
		RunnableImple r=new RunnableImple();//创建一个Runnable类的实现对象
		Thread t=new Thread(r);//创建Thread类对象,构造方法中传递Runnable接口实现类对象
		t.start();//调用Thread类中的Start方法,开始心线程执行run方法
		
		for (int i = 0; i < 20; i++) {
			System.out.println(Thread.currentThread().getName()+"     "+i);
		}
	}

}

区别

  • 第二种方法,避免了单继承的局限性,接口的实现还可以继承与实现其他父类或接口
  • 增强了程序扩展性,降低耦合性,Thread接受什么,可以开启不同的新线程

匿名内部类创建新线程

package java16;

public class InnerClassThreadMain {

	public static void main(String[] args) {
		// 匿名内部类1
		new Thread() {
			@Override
			public void run() {
				for (int i = 0; i < 20; i++) {
					System.out.println(getName()+"i:"+i);
				}
			}
		}.start();
//		
//		for (int j = 0; j < 20; j++) {
//			System.out.println(Thread.currentThread().getName()+j);
//
//		}
		
		//匿名内部类2
		new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 0; i < 20; i++) {
					System.out.println(i+"------2");
				}
				
				}
			}).start();	
		
		//匿名内部类2原例子  RunnableMain
	}

}

Tread的常用方法

获取线程名字

  • getname
  • 先获取正在执行的线程 currentThread 然后用getname
package java16;

public class MyThread extends Thread{
	@Override
	public void run() {
//		String name = getName();
//		System.out.println(name);
//	
//		Thread t = new Thread();
//		Thread currentThread = Thread.currentThread();
//		String name = currentThread.getName();
//		System.out.println(name);
	
		
		System.out.println(Thread.currentThread().getName());
	}
}

package java16;

public class ThreadMain {
	public static void main(String[] args) {
		MyThread m=new MyThread();
		m.start();//thread-0
		
		new MyThread().start();//Thread-1
		new MyThread().start();//Thread-2
		
		
		System.out.println(Thread.currentThread().getName());

	}
}

修改线程的名字

  • setname直接修改
  • 使用构造方法,带参数的,使用父类的方法给子类赋值
    停止当前线程

public static void sleep(long millis)
结束之后继续执行

线程安全

解决线程安全方法
使用同步代码块
synchronized(锁对象){ 可能会出现线程安全的代码}
会降低效率
注意:

  • 锁对象可以使用任意对象
  • 但必须保证多个线程的锁对象是同一个
  • 锁对象作用:
    把同步代码块锁住,只让一个线程执行
package java16;

public class MaiPiao implements Runnable{
	private int ticket=100;

	Object o=new Object();	//锁对象
	@Override
	public void run() {
		for (int i = 0; i < 999; i++) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			synchronized (o) {	同步代码块
				if (ticket>0) {
					System.out.println(Thread.currentThread().getName()+"---------------正在卖"+ticket+"张");
					ticket--;
				}	
			}
		}
			
			
		
	}
}

package java16;

public class MaiPiaoMain {

	public static void main(String[] args) {
		MaiPiao m=new MaiPiao();
		
		Thread t1=new Thread(m);
		Thread t2=new Thread(m);
		Thread t3=new Thread(m);
	
		t1.start();
		t2.start();
		t3.start();
	}

}

②:同步方法

  • 把访问了共享数据的代码抽取出来,放到一个方法中
  • 在方法上添加修饰符synchronized
package java16_1;
//同步方法
public class MaiPiao implements Runnable{
	private /*static*/int ticket=100;

		@Override
	public void run() {
		for (int i = 0; i < 999; i++) {
			
//				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--;
//				
//			}
			method1();//同步方法//静态同步方法
				
		}		
	}

		public /*static*/synchronized void method1() {
		//	synchronized (this) {
				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--;
				
			}	
	//		}
				
		}
}

package java16_1;

public class MaiPiaoMain {

	public static void main(String[] args) {
		MaiPiao m=new MaiPiao();
		
		Thread t1=new Thread(m);
		Thread t2=new Thread(m);
		Thread t3=new Thread(m);
	
		t1.start();
		t2.start();
		t3.start();
	}

}

③:Lock锁

  • 在成员位置创建一个ReentrantLock对象
  • 在可能出现的安全问题之前调用Lock接口中的方法lock获取锁
  • 在可能出现的安全问题后调用unlock方法释放锁
package java16_2;

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

public class MaiPiao implements Runnable{
	private int ticket=100;
	Lock l=new ReentrantLock();
	@Override
	public void run() {
		
		for (int i = 0; i < 999; i++) {
			l.lock();	//获取锁
				if (ticket>0) {
					System.out.println(Thread.currentThread().getName()+"---------------正在卖"+ticket+"张");
					ticket--;
				}	
			l.unlock();	//释放锁
		}
			
			
		
	}
}

package java16_2;

public class MaiPiaoMain {

	public static void main(String[] args) {
		MaiPiao m=new MaiPiao();
		
		Thread t1=new Thread(m);
		Thread t2=new Thread(m);
		Thread t3=new Thread(m);
	
		t1.start();
		t2.start();
		t3.start();
	}

}

等待唤醒----wait/notify

线程之间的通信

package java16;

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("老板我要xx个包子");
					try {
						obj.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println("吃包子");
					System.out.println("------------------------");
				}
			}
			};
		}.start();
		new Thread() {
			public void run() {
				while (true) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					synchronized (obj) {
					System.out.print("花了五秒 做好了--------------");	
					System.out.println("可以吃了");
					obj.notify();
					}
					
				}
			};
		}.start();
	}
}

线程池

package java16.ThreadPool;

public class RunnbleImples implements Runnable{
@Override
public void run() {
	System.out.println(Thread.currentThread().getName()+"创建了新线程");

}
	

}

package java16.ThreadPool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import java16.RunnableImple;

//线程池的代码实现
public class ThreadPoolMain {

	public static void main(String[] args) {
		//创建一定数量的线程池 2个
		ExecutorService es = Executors.newFixedThreadPool(2);
		//调用submit方法,执行run方法
		//两个线程 重复使用
		es.submit(new RunnbleImples());
		es.submit(new RunnbleImples());
		es.submit(new RunnbleImples());
		
		//销毁线程池
		es.shutdown();
		//没了线程池,报错
		
//		es.submit(new RunnbleImples());
	}

}
/*
pool-1-thread-1创建了新线程
pool-1-thread-2创建了新线程
pool-1-thread-2创建了新线程

*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值