标签:
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
主要内容:《 线程组、线程池、JDK5的线程实现方式、 定时器、wait_sleep_yield的在同步方法内的区别、设计模式、单例模式之饿汉式、懒汉式、Runtime类》
我们可以将一些线程进行"分组",分组的目的是可以方便管理,统一进行一些操作;
一.默认线程组:
所有线程,默认都属于一个线程组:main
二.我们可以将一些线程放到我们指定一个"线程组"内;
1).ThreadGroup:它表示一个线程组;
2).实例化我们的线程对象;
3).实例化一个Thread,使用:自定义线程组、线程、线程名称做参数;
三.我们可以对一个线程组内的所有线程进行统一操作,比如:停止一个线程组内的所有线程:
1 public class Demo {
2 public static void main(String[] args) {
3 MyThread t1 = new MyThread();
4 MyThread t2 = new MyThread();
5
6 ThreadGroup g1 = t1.getThreadGroup();
7 ThreadGroup g2 = t2.getThreadGroup();
8 //一.默认情况下,两个线程都属于main线程组;
9 System.out.println("t1的线程组:" + g1.getName());
10 System.out.println("t2的线程组:" + g2.getName());
11
12 //二.自定义线程组
13 ThreadGroup tg = new ThreadGroup("我的线程组");
14 MyThread t3 = new MyThread();
15 MyThread t4 = new MyThread();
16
17 Thread thread1 = new Thread(tg,t3,"线程1");
18 Thread thread2 = new Thread(tg,t4,"线程2");
19
20 System.out.println("thread1的线程组:" + thread1.getThreadGroup().getName());
21 System.out.println("thread2的线程组:" + thread2.getThreadGroup().getName());
22
23 thread1.start();
24 thread2.start();
25
26 try {
27 System.out.println("主进程睡眠两秒......");
28 Thread.sleep(1000 * 2);
29 } catch (InterruptedException e) {
30 // TODO Auto-generated catch block
31 e.printStackTrace();
32 }
33 //三.一次性停掉t3和t4
34 System.out.println("主进程醒来,一次性停掉tg内的所有线程......");
35 tg.interrupt();
36
37
38 }
39 }
40
41 public class MyThread extends Thread{
42 @Override
43 public void run() {
44 for(int i = 0; i < 100;i++){
45 try {
46 Thread.sleep(500);
47 System.out.println(this.getName() + " i = " + i);
48 } catch (InterruptedException e) {
49 System.out.println(this.getName() + " 线程被终止......");
50 break;
51 }
52 }
53 }
54 }
1.我们知道,对于同一个Thread对象,不能重复调用start()方法;
2.如果我们再想使用,只能重新实例化一个新线程对象;如果这种实例化比较耗时,这样效率就很低;
3.这种情况下,可以使用"线程池":
1).它可以缓存一些已经执行过的线程;
2).对于存在于缓存池中的线程,可以直接执行;
3).在JDK5之后,提供了"线程池"的概念:
Executors(类):
public static ExecutorService newCachedThreadPool():创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。
public static ExecutorService newFixedThreadPool(int nThreads):创建一个可重用固定线程数的线程池,
public static ExecutorService newSingleThreadExecutor():创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。新创建的单线程 Executor
返回值:ExecutorService(类):
Future<?> submit(Runnable task):执行并缓存线程对象;
停止线程:
shutdown();
1 public class Demo { 2 public static void main(String[] args) { 3 //**********不使用线程池******************************// 4 /*MyThread t1 = new MyThread();//耗时 5 t1.start(); 6 7 try { 8 Thread.sleep(1000 * 2); 9 } catch (InterruptedException e) { 10 e.printStackTrace(); 11 } 12 //后续代码中,我们还想再次运行一次t1 13 // t1.start();//java.lang.IllegalThreadStateException 14 15 MyThread t2 = new MyThread();//也会耗时5秒; 16 t2.start();*/ 17 //*****************************************************// 18 //使用线程池; 19 ExecutorService service = Executors.newFixedThreadPool(2); 20 21 MyThread t4 = new MyThread(); 22 MyThread t5 = new MyThread(); 23 service.submit(t4);//执行t4并缓存t4 24 service.submit(t5);//执行并缓存t5 25 26 try { 27 Thread.sleep(1000);//等待1秒,为了确保上述两个线程执行完毕; 28 } catch (InterruptedException e) { 29 e.printStackTrace(); 30 } 31 32 //如果后续还需要执行t4和t5 33 System.out.println("******************再次运行t4和t5*****************************"); 34 service.submit(t4);//不会再执行构造方法 35 service.submit(t5);//不会再执行构造方法 36 37 service.shutdown(); 38 39 40 41 } 42 }
1 public class MyThread extends Thread { 2 public MyThread(){ 3 System.out.println("构造一个我很耗时噢,需要5秒......"); 4 for(int i = 1 ;i <= 5 ;i++){ 5 System.out.println("第:" + i + " 秒"); 6 try { 7 Thread.sleep(1000); 8 } catch (InterruptedException e) { 9 } 10 } 11 System.out.println("构造完毕!"); 12 } 13 @Override 14 public void run() { 15 for(int i = 0 ;i < 100; i++){ 16 System.out.println(this.getName() + " i = " + i); 17 } 18 } 19 }
JDK5的实现线程的方式:
步骤:
1.实现Callable接口;
2.重写:call()方法;
3.启动线程:
1.获取线程池:
三种方式:
Executors(类):
public static ExecutorService newCachedThreadPool():创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。
public static ExecutorService newFixedThreadPool(int nThreads):创建一个可重用固定线程数的线程池,
public static ExecutorService newSingleThreadExecutor():创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。新创建 的单线程 Executor
2.调用线程池的
ExecutorService(类):
Future<?> submit(Callable task):执行并缓存线程对象;
1 public class Demo { 2 public static void main(String[] args) { 3 //1.获取一个线程池 4 ExecutorService service = Executors.newFixedThreadPool(2); 5 //2.调用线程池的submit()方法 6 service.submit(new MyCallable()); 7 //3.关闭线程池 8 service.shutdown(); 9 } 10 } 11 12 public class MyCallable implements Callable { 13 14 @Override 15 public Object call() throws Exception { 16 for(int i = 0;i < 100; i++){ 17 System.out.println("i = " + i); 18 } 19 return null; 20 } 21 22 }
1 import java.util.concurrent.ExecutionException; 2 import java.util.concurrent.ExecutorService; 3 import java.util.concurrent.Executors; 4 import java.util.concurrent.Future; 5 /* 6 * 之前我们使用Thread或Runnable中的run()是不能接收返回值的,但 7 * JDK5的线程实现方式,可以接收返回值了。 8 */ 9 public class Demo { 10 public static void main(String[] args) { 11 //1.获取一个线程池 12 ExecutorService service = Executors.newFixedThreadPool(2); 13 //2.调用线程池的submit()方法 14 //Future<?> submit(Callable task) 15 Future<Integer> result = service.submit(new MyCallable()); 16 try { 17 System.out.println("线程计算的结果是:" + result.get()); 18 } catch (InterruptedException e) { 19 e.printStackTrace(); 20 } catch (ExecutionException e) { 21 e.printStackTrace(); 22 } 23 //3.关闭 24 service.shutdown(); 25 } 26 }
1 import java.util.concurrent.Callable; 2 3 public class MyCallable implements Callable<Integer> { 4 5 //计算1--100的累加和,并将结果返回 6 @Override 7 public Integer call() throws Exception { 8 int sum = 0; 9 for(int i = 1 ;i <= 100;i++){ 10 sum += i; 11 } 12 return sum; 13 } 14 15 }
匿名内部类的方式实现多线程程序
1.new Thread(){匿名的Thread的子类};
2.new Thread(匿名的Runnable的子类){};
3.new Thread(匿名的Runnable的子类){匿名的Thread的子类};
1 public class Demo { 2 public static void main(String[] args) { 3 //1.new Thread(){匿名的Thread的子类}; 4 new Thread(){ 5 //重写run() 6 @Override 7 public void run() { 8 System.out.println("a"); 9 } 10 }.start(); 11 12 //2.new Thread(匿名的Runnable的子类){}; 13 new Thread(new Runnable(){ 14 @Override 15 public void run() { 16 System.out.println("b"); 17 } 18 }){}.start(); 19 20 //3.new Thread(匿名的Runnable的子类){匿名的Thread的子类}; 21 new Thread(new Runnable(){ 22 @Override 23 public void run() { 24 System.out.println("c"); 25 } 26 }){ 27 @Override 28 public void run() { 29 System.out.println("d");//最终执行的是子类的run() 30 } 31 }.start(); 32 } 33 }
定时器:
1.在指定的时间,完成指定的任务;
2.在指定的时间开始,每个多长时间,重复的执行指定的任务;
Java中实现定时器:
1.java.util.TimerTask(抽象类):描述具体任务:
1).定义类,继承自:TimerTask;
2).重写run()方法。将具体的任务,写到这里;
2.java.util.Timer类:启动TimerTask的:
1).构造一个Timer对象;使用无参构造方法;
2). public void schedule(TimerTask task, long delay):在指定的delay时间后,执行task中的任务;
public void schedule(TimerTask task,long delay,long period)在指定的delay时间后,执行task中的任务;并且每隔period时间后,会反复的执行;
1 class MyTimerTask extends TimerTask{ 2 private Timer timer; 3 public MyTimerTask(Timer t){ 4 this.timer = t; 5 } 6 @Override 7 public void run() { 8 /*for(int i = 0;i < 100; i++){ 9 System.out.println("i = " + i); 10 }*/ 11 System.out.println("duang......"); 12 // this.timer.cancel();//如果此任务被反复执行,就不需要cancel()了; 13 } 14 } 15 public class Demo { 16 public static void main(String[] args) { 17 Timer timer = new Timer(); 18 System.out.println("5秒后开始执行任务......"); 19 // timer.schedule(new MyTimerTask(timer), 1000 * 5); 20 timer.schedule(new MyTimerTask(timer), 1000 * 5,1000 );//每隔1秒执行一次; 21 // timer.cancel();//终止任务。此方法要在TimerTask中调用,保证任务执行完毕; 22 } 23 }
1.wati():释放锁;Object类的;可以指定时间。使用notify()或notifyAll()唤醒,或者"指定的时间"到了,会自动唤醒;
2.sleep():不释放锁;Thread类:必须指定时间。当休眠时间到,会自动唤醒;
3.yield():不释放锁;Thread类;是当前访问的线程退回到就绪状态。但是,当在"同步"方法中使用时,不会释放锁;
1 public class Demo { 2 public static void main(String[] args) throws InterruptedException { 3 //1.实例化一个Accound 4 Accound acc = new Accound(); 5 //2.实例化两个线程 6 MyThread t1 = new MyThread(acc); 7 MyThread t2 = new MyThread(acc); 8 9 t1.setName("刘亦菲"); 10 t2.setName("周星驰"); 11 12 t1.start(); 13 t2.start(); 14 15 //唤醒。用来测试wait() 16 /*for(int i = 0;i < 10 ;i++){ 17 Thread.sleep(2); 18 acc.show2();//唤醒Accound对象中等待的线程; 19 20 }*/ 21 22 } 23 }
1 public class Accound { 2 public synchronized void show(String threadName){ 3 //************wait()方法************** 4 /* 5 try { 6 System.out.println(threadName + " 开始等待......"); 7 this.wait(); 8 System.out.println(threadName + " 醒来!"); 9 } catch (InterruptedException e) { 10 e.printStackTrace(); 11 } 12 */ 13 14 //************sleep()方法*************** 15 /*try { 16 System.out.println(threadName + " 开始睡眠2秒......"); 17 Thread.sleep(1000 * 2); 18 System.out.println(threadName + " 睡眠醒来!"); 19 } catch (InterruptedException e) { 20 e.printStackTrace(); 21 }*/ 22 23 //***********yield()方法***************** 24 System.out.println(threadName + " 礼让......"); 25 Thread.yield(); 26 System.out.println(threadName + " 礼让结束!"); 27 } 28 //此方法用来测试wait()的 29 public synchronized void show2(){ 30 this.notifyAll(); 31 } 32 }
1 public class MyThread extends Thread{ 2 private Accound acc; 3 public MyThread(Accound acc){ 4 this.acc = acc; 5 } 6 @Override 7 public void run() { 8 for(int i = 0;i < 10;i++){ 9 this.acc.show(this.getName()); 10 } 11 } 12 }
1.模式:人们在长期的生产经营活动中,会反复的遇到一些问题,并使用一些固定的方法去解决这些问题。这种反复的遇到问题并
使用某种方式去解决问题的形式,就叫:模式;
2.Java与模式:以前的程序员在长期的使用Java语言开发过程中,会遇到各种问题,并使用某些手段去解决这些问题,这些手段通常是利用
Java语言的一些特性:继承、封装、多态.....去解决问题;长期以来,就形成了一种固定的方式:就是使用Java语言解决
某种问题的方案。
3.Java中设计模式的分类:
创建型模式
行为型模式
结构型模式
我们以前获取某些对象,都是直接实例化。
这种方式,将实例化对象与前端的代码混杂在一起。
工厂模式:
1.对于某些对象的实例化,先建立某些"工厂类";
2.前端获取对象,不用直接实例化,通过工厂类的某些方法来获取;
3.特点:
1).前端使用对象,不需要自己实例化,通过"工厂类"去获取;
2).如果新增一个产品,需要修改"工厂类";
1 public class Demo { 2 public static void main(String[] args) { 3 //之前的方式,直接实例化对象; 4 Cat c = new Cat(); 5 Dog d = new Dog(); 6 //使用工厂; 7 //方式一: 8 Cat c2 = AnimalFactory.getCat(); 9 Dog d2 = AnimalFactory.getDog(); 10 11 //方式二: 12 Cat c3 = (Cat)AnimalFactory.getAnimal("猫"); 13 Dog d3 = (Dog)AnimalFactory.getAnimal("狗"); 14 15 } 16 } 17 public class AnimalFactory { 18 //*********实现方式一:针对某一种类,都提供一个方法,获取此类对象********** 19 public static Cat getCat(){ 20 return new Cat(); 21 } 22 public static Dog getDog(){ 23 return new Dog(); 24 } 25 26 //*********实现方式二:只提供一个方法,根据参数来判断是获取哪个对象******** 27 public static Object getAnimal(String type){ 28 if(type.equals("猫")){ 29 return new Cat(); 30 } 31 if(type.equals("狗")){ 32 return new Dog(); 33 } 34 return null; 35 } 36 } 37 38 39 public class AnimalFactory { 40 //*********实现方式一:针对某一种类,都提供一个方法,获取此类对象********** 41 public static Cat getCat(){ 42 return new Cat(); 43 } 44 public static Dog getDog(){ 45 return new Dog(); 46 } 47 48 //*********实现方式二:只提供一个方法,根据参数来判断是获取哪个对象******** 49 public static Object getAnimal(String type){ 50 if(type.equals("猫")){ 51 return new Cat(); 52 } 53 if(type.equals("狗")){ 54 return new Dog(); 55 } 56 return null; 57 } 58 } 59 public class Cat { 60 61 } 62 63 public class Dogt { 64 65 }
工厂方法模式的概述和使用
之前的 "简单工厂模式"如果新增一个产品的话,需要修改"工厂类"。
此模式,可以达到当新增产品时,无需修改任何类;
步骤:
1.建立两个接口:
1).产品接口:IAnimal
2).工厂接口:IFactory
2.建立具体的产品类,和具体的工厂类;
1).具体产品:Cat implements IAnimal
2).具体工厂类:CatFactory implements IFactory
好处:如果新增产品时,无需对原来的任何类进行修改;
弊端:类比较多;
1 public class Demo { 2 public static void main(String[] args) { 3 CatFactory catFactory = new CatFactory(); 4 Cat c = (Cat) catFactory.getAnimal(); 5 } 6 } 7 8 public class CatFactory implements IFactory { 9 10 @Override 11 public IAnimal getAnimal() { 12 return new Cat(); 13 } 14 15 } 16 17 18 public interface IAnimal { 19 20 } 21 22 interface IFactory { 23 public IAnimal getAnimal(); 24 } 25 26 public class Cat implements IAnimal { 27 28 }
单例模式之饿汉式
1.单例模式:
单:一个;
例:实例--对象;
2.在我们的程序运行期间,有些类的对象,只需要一个对象,这种情况下,就得需要将此类设计为:单例模式;
3.设计单例模式:例如:将Student设计为单例模式;
步骤:
1.任何类不能实例化Student类的对象:将Student的构造方法私有化;
2.Student内部持有一个自己对象的引用,(饿汉式--先实例化)
3.提供一个公有方法,为外部获取此引用;
1 public class Demo { 2 public static void main(String[] args) { 3 Student stu = Student.getStudent(); 4 Student stu2 = Student.getStudent(); 5 Student stu3 = Student.getStudent(); 6 System.out.println("stu == stu2 : " + (stu == stu2)); 7 System.out.println("stu == stu3 : " + (stu == stu3)); 8 } 9 } 10 11 public class Student { 12 private static Student stu = new Student(); 13 private Student(){ 14 15 } 16 //为了封装,将成员变量私有化,提供公有方法 17 public static Student getStudent(){ 18 return stu; 19 } 20 }
1.在Student内的成员变量,先期不实例化;
2.在公有方法内,先判断是否为null,如果为null再实例化;
3.为了Student类的安全,公有方法可能会被多线程并发访问,为了安全,将
此方法声明为同步的。
1 public class Demo { 2 public static void main(String[] args) { 3 Student stu1 = Student.getStudent();//第一次使用getStudent()方法时,会new一个Student对象; 4 Student stu2 = Student.getStudent();//第二次调用getStudent()方法时,会直接返回一个Student引用; 5 Student stu3 = Student.getStudent(); 6 7 System.out.println("stu1 == stu2 : " + (stu1 == stu2)); 8 System.out.println("stu1 == stu3 : " + (stu1 == stu3)); 9 } 10 } 11 12 public class Student { 13 private static Student stu ; 14 private Student(){ 15 16 } 17 //为了封装,将成员变量私有化,提供公有方法 18 public synchronized static Student getStudent(){ 19 if(stu == null){ 20 stu = new Student(); 21 } 22 return stu; 23 } 24 }
java.lang.Runtime:
每个 Java 应用程序都有"一个" Runtime 类实例.使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前Runtime对象。
内部:单例模式饿汉式实现;
public class Demo { public static void main(String[] args) { Runtime time = Runtime.getRuntime(); try { time.exec("notepad"); time.exec("calc"); } catch (IOException e) { e.printStackTrace(); } } }
标签:
原文地址:http://www.cnblogs.com/linmusen/p/4709283.html