多线程
实现线程的两种方式
一:类名 extends Thread
重写run方法
类名 对象名 = new 类名();
对象名.start(); 启动线程
二、类名 implements Runnable (推荐使用)
重写run方法
类名 对象名 = new 类名();
Thread 对象名1=new Thread(类名);
对象名1.start(); 启动线程
Thread 对象名2=new Thread(类名);
对象名2.start(); 启动线程
线程的生命周期
线程不安全: 多个线程同时修改同一个数据
解决线程不安全的问题: 互斥性
1) 使用同步代码块(在同一个时间点,这个数据只能有一个线程在修改,其他线程只能等这个线程修改完,才能执行) 推荐使用 *
private Object obj = new Object();
synchronized(锁对象){ //对象可以为this,建议自定义为obj
//需要同步的代码(可能修改的代码)
}
注意:
1) 锁对象, 可以是任意对象
2) 这个锁对象是多个线程共享的
同步: 解决线程不安全问题, 缺点: 效率低
2) 使用同步方法
使用同步方法:
在这个方法声明上, snychronized这个关键字, 表示这个方法就是一个同步方法:
1) 非静态的同步方法, 锁对象就是非静态的同步方法所在类的对象: this
等同于: snychronized(this){
}
2) 静态的同步方法, 锁对象就是这个类的class对象
获取某个类的class对象:
1) 类名.class
2) 类的对象.getClass()
3) Class.forName(“包名.类名”)
很少使用:
3) JDK1.5的锁机制
private Lock lock = new ReentrantLock();
lock.lock();
lock.unlock();
推荐: 使用同步代码块
1) 同步代码块比较灵活, 可以是方法的任意一部分,而同步方法就是整个方法都是同步
2) 同步代码块他的锁对象可以任意, 而同步方法锁对象,指定, 非静态的同步方法, 锁对象: this, 静态的同步方法, 这个类的class对象
线程池
代码:
public static void main(String[] args) { //10个任务, 同时执行, 创建10个线程 //使用线程池, 固定数量的线程池 ExecutorService service = Executors.newFixedThreadPool(5); for (int i = 0; i < 10; i++) { MyTask m = new MyTask(); //从线程池,获取线程,执行我们的任务 service.execute(m); } //关闭 service.shutdown(); }
public void run() { // 获取当前系统的时间毫秒值: // 1) new Date() 获取当前系统时间, 调用getTime() 获取毫秒值 底层调用 System类的 currentTimeMillis() // 2) 使用 System类的 currentTimeMillis() System.out.println(Thread.currentThread().getName()+"开始时间"+System.currentTimeMillis()); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"结束时间"+System.currentTimeMillis()); }