多线程的方法总结

/*
1.多线程的实现方法
	A:通过继承自Thread类
		a.把要使用多线程实现的代码封装在一个继承Thread的类中。
		b.重写run方法,把代码放在run方法中。
		c.创建该类的实例,使用start方法开启线程。
		匿名内部类的实现方法:
			new Thread(){
				public void run(){
					System.out.println("这里写要实现功能的代码");
				}
			}.start();
	B:通过实现Runnable接口
		a.把要使用多线程实现的功能封装在一个实现了Runnable接口的类中。
		b.重写run方法,把功能写在run方法中。
		c.创建该类的对象。
		d.以该对象为参数传递给Thread,创建Thread对象。调用Thread对象的start开启线程。
		匿名内部类的实现方法:
			new Thread(new Runnable(){
				public void run(){
					System.out.println("这里写要实现功能的代码");
				}
			}){}.start();
	注:如果使用匿名内部类同时存在实现Runnable接口和Thread子类对象,那么会运行
	子类对象的run方法。
	C:通过线程池实现
		a.写一个实现Runnable接口或实现了Callable接口的实现类
		b.把要用多线程实现的功能写在run方法或call方法中。
		c.创建一个线程池——使用Executors类的静态方法
			public static ExecutorServer newFixedThreadPool(int nThreads);
		d.使用线程池的submit方法开启线程
			注:
				使用Runnable接口实现时没有返回值,但是Callbale的call方法是有返回值的,
				该返回值其实就是call方法的返回值。
				Future<?> submit(Runnable task);
				<T> Future<T> submit(Callable<T> task);
	注:使用线程池时,线程执行完毕后线程池不会关闭,如果需要关闭需要使用shutdown方法
	而通过继承和实现来开启的线程,当线程执行完毕后就自动关闭了。
2.线程的常用方法
	public final void setName(String name)		命名
	public final void getName()						获取名
	public final void setPriority(int newPriority)	设置优先级
	public final int getPriority()						获取优先级
	public finlal void join()								线程加入(等待该线程终止后再执行其他线程)
	public static void yield()							线程礼让
3.特殊方法:
	通过Thread的静态方法获取当前正在执行的线程对象
	pulbic static Thread currentThread();
	
	守护线程,当运行的线程都是守护线程时,java虚拟机会退出
	该方法必须在启用线程前调用才会生效。
	public final void setDaemon(boolean on);
4.同步机制解决线程安全问题
	A:安全问题产生的原因:
		a.有多线程环境
		b.有共享数据
		c.有多条语句操作共享数据
	B:同步代码块:
		把有线程安全问题的代码写在同步代码块中
			synchronized(锁对象){
				需要同步的代码
			}
		同步代码块的锁对象可以是任意的对象,但是必须是同一个对象!
		synchronized的位置问题:
			绝对不能加到run方法上,一旦加到了run方法上就变成了单线程了。
			哪些代码对共享数据操作进加到哪些代码上,但此例中不能使用while(ticket>0),因为
			此代码即是条件判断又是对共享数据的操作,一旦使用这个,则必须放到synchronized中,
			但此时也就相当于是加到了run方法上了。
	C:同步方法:
		直接用synchronized关键字修饰方法名
		此时的锁对象问题:
			非静态方法:锁对象是this
			静态方法:锁对象是this.getCalss()
	D:创建锁对象:
		Lock lock = new ReenTrantLock();
		lock.lock();
			把需要同步的代码,放在中间。
		lock.unlock();
		为了保证锁一定会被释放,可以使用try{...}finally{...}结构,
		把释放锁的操作放到finally中完成。
5.等待唤醒机制解决多线程的通信问题
	不同线程对共享数据操作,至少一个生产者和一个消费者。
	等待唤醒机制是由锁对象来执行的,而同步代码块的锁对象可以是任意对象
	所以wait(),notify(),notifyAll()等方法都定义在Object类中。
	实现:
		定义一个标记标签,来追踪状态——是否有信息
		在设置信息时先做判断,
			如果有信息则等待消费者来取信息s.wait();
			如果没有信息则设置信息,然后更改标签,并唤醒消费端的等待线程s.notyfy();
		同理,在取信息时也要先做判断
			如果有信息则取出,然后更改标签,并唤醒服务端的等待线程s.notify();
			如果没有信息,则等待生产者提供信息s.wait();
6.常见问题
	sleep()和wait()方法的区别
		sleep():必须指时间;不释放锁。
		wait():可以不指定时间,也可以指定时间;释放锁。
	同步的弊端:
		效率较低;
		容易产生死锁问题;
	死锁问题:
		死锁的产生原因:
			两个或两个以上的线程(必须是两个以上的锁对象)在争夺资源的过程中,发生的一种相互等待的现象。
			即:我有一个锁,我拿着我的锁去访问你的资源,同时你也有一个锁,你拿着你的锁来访问我的
			资源,我们俩同时访问对象的资源,但又没有释放自己的锁,所以出现相互等待。
		代码演示:同步中嵌套同步而锁却不同
			public class MyLock {
				// 创建两把锁对象
				public static final Object objA = new Object();
				public static final Object objB = new Object();
			}
			public class DieLock extends Thread {
				private boolean flag;
				public DieLock(boolean flag) {
					this.flag = flag;
				}
				@Override
				public void run() {
					if (flag) {
						synchronized (MyLock.objA) {
							System.out.println("if objA");
							synchronized (MyLock.objB) {
								System.out.println("if objB");
							}
						}
					} else {
						synchronized (MyLock.objB) {
							System.out.println("else objB");
							synchronized (MyLock.objA) {
								System.out.println("else objA");
							}
						}
					}
				}
			}
			public class DieLockDemo {
				public static void main(String[] args) {
					DieLock dl1 = new DieLock(true);
					DieLock dl2 = new DieLock(false);

					dl1.start();
					dl2.start();
				}
			}
7.特殊的线程类TimerTask
	与Timer类配合使用来执行定时任务
	可以让我们在指定的时间做某件事情,还可以重复的做某件事情
	Timer——定时——的常用方法
		public Timer();	构造方法
		public void schedule(TimerTask task,long delay);	delay毫秒后执行task任务
		public void schedele(TimerTask task,long delay,long period);
		delay毫秒后执行task任务,然后每个period毫秒再执行一次。
		public void schedule(TimerTask task, Date time)		在指定的时间执行task任务
		public void schedule(TimerTask task, Date firstTime, long period)
		在指定的时间执行task任务,然后每隔period毫秒再执行一次
		public void cancel();		取消任务
	TimerTask——定时任务——是一个抽象的线程类,把任务写在run方法中
	实例:在指定的时间删除我们的指定目录
		class DeleteFolder extends TimerTask {
			@Override
			public void run() {
				File srcFolder = new File("demo");
				deleteFolder(srcFolder);
			}
		}
		public class TimerTest {
			public static void main(String[] args) throws ParseException {
				Timer t = new Timer();
				String s = "2014-11-27 15:45:00";
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				Date d = sdf.parse(s);
				t.schedule(new DeleteFolder(), d);
			}
		}
*/



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一夸克

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值