Java 多线程
2016-04-19 23:15
621 查看
1.java多线程的两种形式
1.1Thread子类形式
public class MyThread extends Thread{ @Override public void run() { for (int i=0;i<500;i++){ System.out.println( getName()+":"+i); } } } public class ThreadDemo { public static void main(String[] args) throws InterruptedException { MyThread myThread1=new MyThread(); MyThread myThread2=new MyThread(); myThread1.start(); myThread2.start(); System.out.println("over..."); } }
1.2 Runable形式
class MyRunable implements Runnable{ @Override public void run() { for (int i=0;i<200;i++){ //注意这里调用线程名称的方式 System.out.println(Thread.currentThread().getName() + ":" + i); } } } public class ThreadRunableDemo { public static void main(String[] args) { Runnable r1= new MyRunable(); new Thread(r1,"clow").start(); new Thread(r1,"jop").start(); //当然也可以使用内部类 Runnable r2=new MyRunable(){ @Override public void run() { for (int i=10;i<120;i++){ //注意这里调用线程名称的方式 System.out.println(Thread.currentThread().getName() + ":" + (char)i); } } }; new Thread(r2,"alex").start(); } }
1.3 内部类线程
内部类可以类比于C#的委托-拉姆达表达式,同层次的变量在run方法是可以直接使用的,这和拉姆达表达式一样public class InnerThreadDemo { public static void main(String[] args) { //继承Thread类实现多线程 new Thread(){ @Override public void run() { for (int i=0;i<1000;i++){ System.out.println(Thread.currentThread().getName()+": "+i); } } }.start(); //使用Runnable实现 new Thread(new Runnable() { @Override public void run() { for (int i=0;i<1000;i++){ System.out.println(Thread.currentThread().getName()+": "+i); } } }).start(); } }
1.4二者的比较
Runable解决了java单继承类的局限问题,而且它减少了代码的耦合性,所有推荐使用第二种方法!2.电影票问题
假设一家电影院有3个电影售票窗口,同时出售《复仇者联盟4》的电影票共100张,如何模拟?2.1Thread子类实现形式
class TicketTread extends Thread { private static int ticketnum = 100; @Override public void run() { while(ticketnum>0){ System.out.println("windows_"+ getName()+":The current ticket number is "+ticketnum--); } } } class TicketTreadDemo { public static void main(String[] args) { TicketTread t1=new TicketTread(); TicketTread t2=new TicketTread(); TicketTread t3=new TicketTread(); t1.start(); t2.start(); t3.start(); } }
2.2Runable 实现形式
class Ticket implements Runnable { private int ticketnum = 100; @Override public void run() { while(ticketnum>0){ System.out.println("windows_"+Thread.currentThread().getName()+":The current ticket number is "+ticketnum--); } } } class TicketRunableDemo { public static void main(String[] args) { Ticket t =new Ticket(); new Thread(t,"1").start(); new Thread(t,"2").start(); new Thread(t,"3").start(); } }
从上面的2例子可以看出对于相同的代码,使用runable的方法更灵活方便,但是他们都还存在一个问题,比如某一张票会被卖了2次,这就是所谓的临界区问题了。
2.3Runable 最终实现形式
如上的售票必须使用同步才行,java的synchronized方法和C#的lock方法类似。class Ticket implements Runnable { private int ticketnum = 100; private Object obj = new Object(); @Override public void run() { synchronized (obj) { while (ticketnum > 0) { System.out.println("windows_" + Thread.currentThread().getName() + ":The current ticket number is " + ticketnum--); } } } }
当然也可以使用同步方法放在run里面,但类是实例类的时候,它锁的对象的this; 当方法是静态的时候,它锁的是类的Xxx.class的字节码对象
public synchronized void sellTicket(){ while (ticketnum > 0) { System.out.println("windows_" + Thread.currentThread().getName() + ":The current ticket number is " + ticketnum--); } }
继jdk5推出了类似PV操作的上锁和解锁操作
class Ticket implements Runnable { private int ticketnum = 100; Lock lock=new ReentrantLock(); //实例化一个锁 @Override public void run() { try { lock.lock(); //上锁 while (ticketnum > 0) { System.out.println("windows_" + Thread.currentThread().getName() + ":The current ticket number is " + ticketnum--); } }finally { lock.unlock(); //解锁 } } }
2.线程池
1.Runable类型lass ThreadPool implements Runnable { @Override public void run() { for (int i=0;i<200;i++){ System.out.println(Thread.currentThread().getName()+" "+i); } } } class ThreadPoolDemo{ public static void main(String[] args) { ExecutorService pool= Executors.newFixedThreadPool(2);//创建包含2个线程的线程池 pool.submit(new ThreadPool()); pool.submit(new ThreadPool()); //此时线程执行完会被回收,使用下面方法结束线程池 pool.shutdown(); } }
2.Callable类型
其和C#中的BackgroundWork类似,都是执行一段代码并返回结果。而在java中其自动阻塞主线程效果
class MyCallable implements Callable<Integer> { private int number; public MyCallable(int number){ this.number=number; } @Override public Integer call() throws Exception { int sum=0; for (int i=1;i<=number;i++){ sum+=i; } Thread.sleep(7000); return sum; } } class MyCallableDemo{ public static void main(String[] args) throws Exception { ExecutorService pool= Executors.newFixedThreadPool(2); Future<Integer> f1=pool.submit(new MyCallable(100)); Future<Integer> f2=pool.submit(new MyCallable(200)); int i1=f1.get(); int i2=f2.get(); System.out.println("打印输出"); System.out.println(i1);//5050 System.out.println(i2);//20100 } }
3.定时器
如下代码为当前显示时间//schedule(TimerTask task, long delay, long period) //period为时间间隔 class MyTask extends TimerTask{ @Override public void run() { System.out.println(new Date().toString()); } } class TimerDemo { public static void main(String[] args) { Timer t=new Timer(); TimerTask task=new MyTask(); t.schedule(task, 0, 1000); //第一次无延迟,每秒执行一次 //t.cancel(); //干掉时间任务的子线程,才能推出主线程 System.out.println("over.."); } }
相关文章推荐
- Java语言基础1
- Java语言基础2
- Java Set简单用法
- spring事务管理几种方式(转)
- 20145229吴姗珊 《Java程序设计》2天小总结
- 【SSH进阶之路】Struts + Spring + Hibernate 进阶开端(一)
- leetcode 46,47. Permutations I/II 全排列问题 java
- 关于cmd命令运行java文件class
- Spring技术内幕——深入解析Spring架构与设计原理收藏
- Java中使用native2ascii工具处理.properties文件
- java命令行路径
- Java对象的序列化和反序列化
- java 算法
- java动态代理(JDK和cglib)
- java修饰符汇总
- Java 7新特性:自动化资源管理
- java 用hmac-sha1进行签名
- 【java项目实战】代理模式(Proxy Pattern),静态代理 VS 动态代理
- java线程安全总结
- 【java项目实践】详解Ajax工作原理以及实现异步验证用户名是否存在+源码下载(java版)