多线程
一、多线程的创建
- 创建一个继承thread类的子类
- 重写thread类的run方法
- 子类实例化
- 通过对象调用start方法
不能通过调用run方法启动线程,这样不算多线程,只算运行方法 - 已过时不建议使用
四、多线程创建方式2
- 创建一个实现了Runnable()接口的类
- 实现类去实现runnable中的抽象方法,run()
- 实现类实例化
- 将此对象作为参数传递到Thread类的构造器中,创建类的对象
- 通过Thread类的对象调用start()
五、比较创建线程的两种方式开发中优先选择Runnable接口的方式原因: - 实现的方式没有类的单继承性的局限性
- 实现的方式更适合用来处理多个线程有共享的数据方式
联系:都需要重写run,将线程的执行方式写在run方法内
六、线程的生命周期五种状态:
- 新建
- 就绪 start
- 运行 获取cpu执行权
- 阻塞 sleep、join、同步锁、wait、suspend
- 死亡 stop
七、线程同步(解决线程安全问题①) 方式一:同步代码块
synchronized(同步监视器){//需要同步的代码} - 说明:操作共享数据的代码,即为需要被同步的代码
- 共享数据:多个线程共同操作的变量
- 同步监视器:俗称:锁。任何类的对象都可以操作
- 要求:多个线程必须共用同一把锁
- tips:可以使用当前对象this、window2.class(用类去充当)
方式二:同步方法 (注意多个线程是否使用同一个this)在方法处标明synchronized,在方法内类似于代码块,默认this是监视器,包含的内容要多注意注意使用静态方法和静态变量
死锁问题:两个线程都在等待对方的另一个同步数据的同步锁,不会异常不会报错解决:
- 专门的算法、原则
- 减少同步资源的定义
- 避免嵌套同步
八、lock锁(解决线程安全问题②)——JDK5.0新增privateReentrantLocklock=new ReentrantLock();lock.lock();lock.unlock();synchronized与lock的对比lock需要手动开关、lock只有代码块锁synchronize的推出作用域自动关闭、synchronized既有代码块锁又有方法锁
九、线程通信 wait();进入阻塞并释放同步监视器 notify();唤醒wait的一个线程,如果多个线程被wait,唤醒优先级最高* notifyall();唤醒所有被wait的线程必须在同步代码块或者同步方法里使用这三个方法的调用者必须是同步方法或者同步代码块的同步监视器
面试题:sleep和wait的异同
- 相同点:都可以使方法进入阻塞
- 不同点:
- 两个方法声明的位置不同,thread声明sleep,Object声明wait()
- 调用的方法:sleep可以在任何需要的场景、wait必须在同步代码块中
- 同步监视器:如果两个方法都在同步代码块和同步方法中,sleep不会释放同步监视器、wait会释放
十、JDK5.0新增的线程创建方式方式一、Callaable接口
- 相比run()方法,可以有返回值
- 方法可以抛出异常
- 支持泛型返回值
- 需要借助FutureTask类,比如获取返回值
ExecutorService service = Executors.newFixedThreadPool(10);2、执行指定的线程操作。需要提供runnable接口或者callable接口的实现类service.execute(newThreadnumber());//适合使用Runnableservice.submit();//适合使用callable3、关闭连接池service.shutdown();好处:1、提高响应速度(减少了线程的创建)2、降低了资源消耗(重复利用线程池中的线程)3、便于线程管理