多线程的方法总结

来源:互联网 发布:mac os 安装盘制作 编辑:程序博客网 时间:2024/06/01 15:03

/*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;}@Overridepublic 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 {@Overridepublic 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 0
原创粉丝点击