一,多线程创建方式一继承Thread类创建线程
假如你现在还在为自己的技术担忧,假如你现在想提升自己的工资,假如你想在职场上获得更多的话语权,假如你想顺利的度过35岁这个魔咒,假如你想体验BAT的工作环境,那么现在请我们一起开启提升技术之旅吧,详情请点击http://106.12.206.16:8080/qingruihappy/index.html
Thread类本质上是实现了Runnable接口的一个实例,代表一个线程的实例。启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个新线程,并执行run()方法。这种方式实现多线程很简单,通过自己的类直接extend Thread,并复写run()方法,就可以启动新线程并执行自己定义的run()方法。例如:
1 public class MyThread extends Thread { 2 public void run() { 3 System.out.println("MyThread.run()"); 4 } 5 } 6 7 MyThread myThread1 = new MyThread(); 8 MyThread myThread2 = new MyThread(); 9 myThread1.start(); 10 myThread2.start();
这种方式主要的原理就是继承了tread类,当
我们来看一下源码当调用start方法的时候,就会调用start0的方法,而start0有一个native关键字,我们可以理解成当调用start0的时候才去调用了run的方法。
1 public synchronized void start() 2 { 3 boolean flag; 4 if(threadStatus != 0) 5 throw new IllegalThreadStateException(); 6 group.add(this); 7 flag = false; 8 start0(); 9 flag = true; 10 try 11 { 12 if(!flag) 13 group.threadStartFailed(this); 14 } 15 catch(Throwable throwable) { } 16 break MISSING_BLOCK_LABEL_70; 17 Exception exception; 18 exception; 19 try 20 { 21 if(!flag) 22 group.threadStartFailed(this); 23 } 24 catch(Throwable throwable1) { } 25 throw exception; 26 } 27 28 private native void start0();
二、实现Runnable接口创建线程
如果自己的类已经extends另一个类,就无法直接extends Thread,此时,可以实现一个Runnable接口,如下:
1 public class MyThread extends OtherClass implements Runnable { 2 public void run() { 3 System.out.println("MyThread.run()"); 4 } 5 }
为了启动MyThread,需要首先实例化一个Thread,并传入自己的MyThread实例:
1 MyThread myThread = new MyThread(); 2 Thread thread = new Thread(myThread); 3 thread.start()
事实上,当传入一个Runnable target参数给Thread后,Thread的run()方法就会调用target.run(),参考JDK源代码:
1 public void run() { 2 if (target != null) { 3 target.run(); 4 } 5 }
这里应用了典型的回掉函数,A调用B,B在调用A,在定义一个接口定义准则,确定规范。
三,匿名函数创建
匿名函数必须要继承父类或者实现接口的。
有时候我们只用一次的话那么就可以用匿名函数了。
1 new Thread() {//创建方式1 2 public void run() { 3 for(int x=0; x<50; x++) { 4 System.out.println(Thread.currentThread().getName()+"....x="+x); 5 } 6 } 7 }.start();
1 new Thread(new Runnable() {//创建方式2 2 public void run() { 3 for(int x=0; x<50; x++) { 4 System.out.println(Thread.currentThread().getName()+"....z="+x); 5 } 6 } 7 }).start();
四,创建带返回值的多线程
一:创建自己的对象实现Callable<Object> 接口
二:重写call方法
三:创建线程池
四:通过线形池submit返回future对象
五:通过future获取任务的返回值
六:关闭线程
1 public class CallableFutureTest { 2 public static void main(String[] args) throws ExecutionException, InterruptedException { 3 CallableFutureTest test = new CallableFutureTest(); 4 // 创建一个线程池 5 ExecutorService pool = Executors.newFixedThreadPool(2); 6 // 创建两个有返回值的任务 7 Callable c1 = test.new MyCallable("A"); 8 Callable c2 = test.new MyCallable("B"); 9 // 执行任务并获取Future对象 10 Future f1 = pool.submit(c1); 11 Future f2 = pool.submit(c2); 12 // 从Future对象上获取任务的返回值,并输出到控制台 13 System.out.println(">>>" + f1.get().toString()); 14 System.out.println(">>>" + f2.get().toString()); 15 // 关闭线程池 16 pool.shutdown(); 17 } 18 class MyCallable implements Callable { 19 private String oid; 20 MyCallable(String oid) { 21 this.oid = oid; 22 } 23 public Object call() throws Exception { 24 return oid + "任务返回的内容"; 25 } 26 } 27 }
五,spring创建多线程
加载xml文件
在ApplicationContext.xml文件里面添加
1 xmlns:task="http://www.springframework.org/schema/task"
xmlns文件并且xsi:schemaLocation中添加
1 http://www.springframework.org/schema/task
1 http://www.springframework.org/schema/task/spring-task.xsd
在spring中配置Executor
在ApplicationContext.xml文件里面添加
1 <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> 2 <!-- 核心线程数 --> 3 <property name="corePoolSize" value="${task.core_pool_size}" /> 4 <!-- 最大线程数 --> 5 <property name="maxPoolSize" value="${task.max_pool_size}" /> 6 <!-- 队列最大长度 --> 7 <property name="queueCapacity" value="${task.queue_capacity}" /> 8 <!-- 线程池维护线程所允许的空闲时间,默认为60s --> 9 <property name="keepAliveSeconds" value="${task.keep_alive_seconds}" /> 10 </bean> 11 <!-- 注解式 --> 12 <task:annotation-driven />
在dbconfig.properties添加
1 maxOpenPreparedStatements=20 2 removeAbandoned=true 3 removeAbandonedTimeout=1800 4 logAbandoned=true
添加依赖注入
在所需要的service或者controller类里面添加
1 @Resource(name = "taskExecutor") 2 private TaskExecutor taskExecutor;
使用线程池进行并发操作
代码如下
1 taskExecutor.execute(new Runnable() { 2 3 @Override 4 public void run() { 5 // TODO Auto-generated method stub 6 try { 7 //要进行的并发操作 8 } catch (Exception e) { 9 // TODO Auto-generated catch block 10 e.printStackTrace(); 11 } 12 } 13 });
提示
1 @Controller 2 public class IndexController { 3 int studentscount = 0; 4 @RequestMapping(value = "/index.html") 5 public ModelAndView goIndex() { 6 logBefore(logger, "列表Center"); 7 ModelAndView mv = this.getModelAndView(); 8 taskExecutor.execute(new Runnable() { 9 10 @Override 11 public void run() { 12 // TODO Auto-generated method stub 13 // 得到所有学生人数 14 try { 15 studentscount = coursesService.getStudentCount(pd); 16 } catch (Exception e) { 17 // TODO Auto-generated catch block 18 e.printStackTrace(); 19 } 20 21 } 22 }); 23 mv.addObject("studentscount", studentscount); 24 mv.setViewName("common/index"); 25 return mv; 26 }