线程的匿名内部类
匿名内部类对象格式:
new 父类类型(){
抽象父类的方法、
}
最终得到的就是父类类型的子类对象
有两种方式,1:创建线程对象时,直接重写Thread类中的run方法
1 // 继承thread//创建线程任务和线程对象 2 new Thread(){ 3 public void run() { 4 for (int i = 0; i <100; i++) { 5 System.out.println(Thread.currentThread().getName()+":"+i); 6 } 7 } 8 }.start();
2:使用匿名内部类的方式实现Runnable接口,重新Runnable接口中的run方法
Runnable r=new Runnable(){ public void run(){ for (int i = 0; i <100; i++) { System.out.println(Thread.currentThread().getName()+":"+i); } } }; //创建线程对象 Thread t=new Thread(r); //开启线程 t.start();
线程池
为了避免重复的创建线程,线程池的出现可以让线程进行复用。通俗点讲,当有工作来,就会向线程池拿一个线程,当工作完成后,并不是直接关闭线程,而是将这个线程归还给线程池供其他任务使用。
线程池的使用我们主要是通过Runnable接口、Callable接口来实现;
Runnable接口的使用:
1.从线程池工厂(Executor)对象中获取线程池(ExecutorService)对象
2.让线程池对象从池子中选一条空闲的线程执行线程任务,没有等待,用完放回
3.没有对象销毁线程池
1 MyRunnable mr=new MyRunnable(); 2 ExecutorService es=Executors.newFixedThreadPool(2); 3 ExecutorService es2=Executors.newFixedThreadPool(10); 4 es.submit(mr); 5 es.submit(mr); 6 es.submit(mr); 7 es2.submit(mr); 8 es.shutdown(); 9 es2.shutdown();
Callable接口的使用:
与Runnable接口功能相似,用来指定线程的任务。其中的call()方法,用来返回线程任务执行完毕后的结果,call方法可抛出异常。
这里讲一下Future接口,他用来记录线程任务执行完毕后产生的结果。线程池创建与使用,Runnable接口和Callable接口都可以使用。
例:
1 //创建线程任务 2 MyCallable mc=new MyCallable(); 3 //获取线程池对象 4 ExecutorService es=Executors.newFixedThreadPool(2); 5 //获取future对象 6 Future<String> f = es.submit(mc); 7 //从future对象中获取返回值 8 String s=f.get(); 9 System.out.println(s); 10 //销毁线程池 11 es.shutdown();
MyCallable.java:
运行之后得到的是返回值
线程安全
当若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。
线程同步的方式有两种:一是同步代码块,二是同步方法;
同步代码块:在代码块声明上 加上synchronized
基本格式:
synchronized(非匿名的任意对象){
线程要操作的共享数据
}
例:
1 //创建锁对象 2 private Object obj=new Object(); 3 public void run() { 4 while(true){ 5 synchronized (obj) { 6 7 8 if (ticket>0) { 9 try { 10 Thread.sleep(300); 11 } catch (InterruptedException e) { 12 // TODO Auto-generated catch block 13 e.printStackTrace(); 14 } 15 System.out.println(Thread.currentThread().getName()+"窗口卖了第"+ticket--+"张票"); 16 } 17 } 18 } 19 }
synchronized(obj)中的obj相当于是一个同步锁,没有get到锁的线程不能进入同步,在同步中的线程如果没有运行到synchronized的最后,则不会释放锁
另外,加上了线程同步之后,程序的运行速度会明显减慢
可能会产生线程安全问题的代码
}
Lock接口
提供了获得锁lock()和释放锁unlock()两个方法