Thread
程序 进程 线程 守护线程
程序 : 为完成特点定任务,使用某种语言编写的一些指令的集合
进程 : 正在运行的一个程序
线程 : 进程细化为线程 线程是执行进程的路径
守护线程 程序在运行时 后台提供的一种通用的服务线程 比如垃圾回收机制是一种特殊的守护线程
我们可以在start()前调用setDaemon()使线程成为守护线程
并行 并发
并行 : 多个CPU执行多个任务
并发 : 一个CPU(分时间片)执行多个任务 在一段时间间隔执行
创建线程的方式 4种
1 继承Thread 重写run() 2实现Runnable接口 重写run()
1和2都有重写run() 启动线程都是调用start() Thread是Runnable的子类
考虑使用实现的方法 继承的局限性 实现的方法对共享的数据处理更灵活
3 实现Callable接口 重写call() 使用FutureTask来创建线程 也能获取返回值
4使用线程池 Executors的静态方法 使用execute方法或者submit方法
线程池避免了繁琐的创建和销毁线程 有效的利用了资源 还可以通话ThreadPoolExecutor设置一些属性
start()和run()
启动线程调用start()只能调用一次 线程要执行的代码写在run()里 可以多次调用
Runnable 和 Callable
Callable有返回值 可以用FutureTask来获取 可以抛异常 支持泛型
线程的方法
currentName() 当前线程的名字 get/setName() 获取/设置线程名
join() 加入另外的线程 yield()交出CPU执行权 sleep(long time) 使线程睡眠
suspend( ) 挂起线程 resume() 恢复线程 stop() 停止线程 —–>这三个方法不建议使用
start() 启动线程 run() 线程要执行代码写在里面 priority()优先级 有三个1,5,10
wait() 等待 notify/notifuAll() 唤醒一个/多个线程—–>这三个方法定义在Object中
线程的生命周期
在Thread中定义了一个Emun类有6个对象
NEW新建 RUNNABLE BLOCKED WAITING TIMED_WAITING TERMINATED
可以看做新建 就绪 运行 阻塞 死亡
新建 调用start() 到就绪
就绪 获得CPU执行权 到运行 运行 失去CPU执行时间/调用yield() 到就绪
运行 run()执行完/Error或者Excepion方式未处理/调用stop() 到死亡
运行 join()/wait()/suspend()/sleep()/等待同步锁 到阻塞
阻塞 等待join线程结束/notify()或者notifyAll()/resume()/等待sleep时间结束/获取同步锁 到就绪
同步和异步
同步 : 同时发送请求 要等上一个请求结束 下一个请求才可以发送
异步 : 同时发送请求 不用等上一个请求结束 可继续发送请求
- 同步:发送一个请求,等待返回,然后再发送下一个请求
- 异步:发送一个请求,不等待返回,随时可以再发送下一个请求
同步涉及的安全问题
多线程同时操作数据 不安全 Java使用同步机制解决
1同步代码块
1 | synchronized(同步监视器){ |
2 | //多个线程要共同操作的数据 |
3 | } |
共享数据就是多个线程要共同操作的数据 注意不能多 不能少
同步监视器(锁) 任何对象都可以充当 多个线程必须共用一把锁
实现Runnable的默认同步监视器的this
继承Thread的要慎用this 建议使用当前类
2同步方法 当一个方法里都是共享数据 我们加上synchronized修饰
3Lock 使用ReentrantLock 要手动加锁 使用lock()和手动释放锁unLock
建议选择lock—>同步代码块—>同步方法
notify()和notifyAll()
notify()唤醒一个线程 notifyAll()唤醒多个线程
sleep()和wait()
sleep()可以在任何需要的地方声明 wait()只能在同步代码块或者同步方法里调用
同时在同步代码块或者同步方法里sleep()不释放锁 wait()释放锁
sleep()是Thread的方法 wait()是Object的方法
都可以造成线程阻塞 JDK8中都有捕获InterruptException