JAVA多线程
一、线程体
*用run()方法实现
*线程启动后,系统自动调用run()方法
*通常,run()方法执行一个事件较长的操作
二、创建线程的两种方法
(1)通过继承Thread类创建线程
class MyThread extends Thread{ @Override public void run(){...} } }
(2)通过向Thread类构造方法传递Runnable对象创建线程
class MyTask implements Runnable{ public void run(){...} } Thread thread =new Thread(mytask); thread.start();
*可用匿名类实现Runnable
new Thread(){ public void run(){...} }.start();
*可用Lambda表达式
new Thread(()->{...}).start();
三、线程同步
*每个对象都对应于一个monitor(监视器),有一个称为“互斥锁”的标记,用来保证在任一时刻只能有一个线程访问该对象
*关键字synchronized用来与对象的互斥锁联系
*使用wait()方法可以释放对象锁
使用notify()或notifyAll()可以让等待的一个或所有线程进入就绪状态
wait();->notify()
例子:
class CubbyHole{ private int index=-; private int []data=new int[3]; public synchronized void put(int value){ while(index==data.length){ try{ this.wait(); }catch(InterruptedException e){} } data[intdex]=value; index++; this.notify(); } public synchronized void get(){ while(index<=0){ this.wait(); }catch(InterruptedException e){} index--; int val=data[index]; this.notify(); } }
四、原子变量及线程安全的集合
(1)java.util.concurrent.atomic包
*AtomicInteger类(原子变量) 使用AutomicInteger修饰变量实现该变量同步
(2)java.util.concurrent包中并发的集合类
*JDK1.5以前:
ArrayList/HashMap不是线程安全的,而Vector和HashTable是线程安全的
产生一个线程安全的集合对象的方法:
Collections.synchronizedArrayList(list);
*JDK1.5以后:
CopyOnWriteArrayList、CopyOnWriteArraySet类:适合于很少写入而读取频繁的对象
还有ConcurrentHashMap、ArrayBlockingQueue(实现生产者和消费者put()\get()方法)等
五、线程池
(1)相关的类:ExecutorServie接口、TreadPoolExecutor类、Executors工具类
(2)常用方法:
ExecutorServicePool pool=Executors.newCachedThreadPool(); pool.execute(t);//t为实现Runnable的类
(3)使用Timer
*java.util.Timer类(每隔一段时间重复执行某一件事)
*javax.swing.Timer类(每隔一段时间重复执行ActionListener)
(4)特别注意:
在线程中更新图形化界面,要调用SwingUtilities.invokeLater(Runnable对象)
六、流及并行流
(1)*得到流:Stream<T> stream=collection.stream();
*操作流:int sumOfWeights=blocks.stram()
.filter(过滤条件)
.mapToInt()
...
(2)流的并行计算:
将.stream()换成.parallelStream()即可
List<Integer> a=Arrays.aslist)(1,2,5,7,3); System.out.println( a.parallelStream() .mapToInt(i->(int)i) .filter(i->i>2)//过滤 .map(i->i*i) .sorted()//排序 .distinct()//去重 .limit(10)//取10个 .max()//取最大 );