多线程-Thread类、Runnable接口、线程池、线程安全与同步
为了实现多部分代码同时执行;
Thread类:1.继承Thread类:定义一个类继承Thread,重写run方法,创建子类对象,调用start方法,开启线程
2.实现Runnable接口:避免了单继承的局限性,
//分别用两条线程同时计算1-100的和,1-200的和 public static void main(String[] args) throws InterruptedException, ExecutionException { //获取线程池对象 ExecutorService es=Executors.newFixedThreadPool(2); //创建线程任务对象 MySum m1=new MySum(100); MySum m2=new MySum(200); //提交线程任务 Future<Integer> f1=es.submit(m1); Future<Integer> f2=es.submit(m2); //获取返回值 System.out.println(f1.get()); System.out.println(f2.get()); //销毁线程池 es.shutdown(); }
public class MySum implements Callable<Integer> { private int n; public MySum(){} public MySum(int n){ this.n=n; } public Integer call() throws Exception { int sum=0; for(int i=1;i<=n;i++){ sum+=i; } return sum; } }
匿名内部类:1.创建线程对象时,直接重写Thread类中的run方法
2.使用匿名内部类的方式实现Runnable接口,重新Runnable接口中的run方法
线程池:1.Runnable接口:①创建线程池 ②创建线程任务对象 ③提交线程任务 ④ 获取返回值 ⑤ 销毁线程池
2.Callable接口:
有返回值用Runnable,
例题:
public class MySum implements Callable<Integer> { private int n; private int m; public MySum(){} public MySum(int n,int m){ this.m=m; this.n=n; } public Integer call() throws Exception { int num1=0; int num2=0; int sum=0; int Sum=0; for(int i=1;i<n;i++){ num1=sum+=i; } for(int i=1;i<m;i++){ num2=sum+=i; } Sum=num1+num2; return Sum; } }
测试类代码
public static void main(String[] args) throws InterruptedException, ExecutionException { //获取线程池对象 ExecutorService es=Executors.newFixedThreadPool(2); //创建线程任务对象 MySum m1=new MySum(20,50); MySum m2=new MySum(60,300); //提交线程任务 Future<Integer> f1=es.submit(m1); Future<Integer> f2=es.submit(m2); //获取返回值 System.out.println(f1.get()); System.out.println(f2.get()); System.out.println(f1.get()+f2.get()); //销毁线程池 es.shutdown(); }
线程安全案例:电影院卖票
public class Ticket implements Runnable { private int ticket=100; public void run() { while(true){ if(ticket>0){ try { Thread.sleep(50); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"卖出了第"+ticket--+"张票"); } } } }
public class Demo01 { public static void main(String[] args) { //创建线程任务 Ticket r=new Ticket(); //创建线程对象 Thread t1=new Thread(r); Thread t2=new Thread(r); Thread t3=new Thread(r); //开启线程 t1.start(); t2.start(); t3.start(); } }
线程安全问题处理:1.同步代码块:在代码块声明上 加上synchronized
同步代码块中的锁对象可以是任意的对象;但多个线程时,要使用同一个锁对象才能够保证线程安全
2.同步方法:在方法声明上加上synchronized
同步方法中的锁对象是 this