例子1引入线程概念
通过得到当前线程方式循环主线程做某事
例子2
演示了在主线程之外开启多个线程的基本方式 ( new一个extends Thread )
例子3 ( task extends Thread )
演示了 把线程类做为一个窗口组件的一个属性
当按钮按下时 会new一个task
(start在task的构造器中)
这样就实现了按下按钮时启动一个任务 另一个按钮则修改run中的标志
可在run中根据标志决定做什么事
或sleep( action button 都做为窗口类的内部类)
例子4 ( task extends Thread )
另一种写法 通过内部类的方式重新写 例子3
注意的是 内部类的权限是
private 的
都差不多 只不过是把task 写在窗口类里面(task action button 都做为窗口类的内部类)
例子5
主线程实现 Runnable接口 意思是提供一个run方法
就是说给出一段任务代码
要执行任务的时候这样办 new
Thread(提供的run方法的对象).start();
意思就是 任务代码写在窗口类中 而启动线程代码写在 Thread
中
要启动是就要new一个Thread对象来进行帮助
(与上面的例子有区别,上面的例子是 先做儿子 从父亲那继承 启动线程的相关代码)
例子6
启动多个线程的例子
因为你一个类只能提供一个run方法OK ,所以呢你要么就是
专门准备几个 带run方法的task
(不认Thread 做干爹)
然后呢在需要启动线程时去求Thread 给几个实例来帮助启动
或者呢
准备几个认Thread 做干爹的 task 然后它们自己就能 start了
例子7
Daemon线程
setDaemon 改状态
isDaemon 查状态
Daemon为真是 开启的线程
为Daemon
守护线程 个人理解就是不受中断干扰的线珵 设为true时 就屏蔽所有中断干扰只有非守护线程结束时才退出
(其它线程会受中断干扰 如
ctrl+c 及其它IO操作产生的中断)
之所以不要用守护线程去IO 是因为它不会受中断影响而结束 但是请求不成功会产生
错误如读不到内容却一直读
从而不断的产生IO错误(非守护线程IO错误后会中断,而守护线程不受中断控制,从而产生
异常情况中断,访存错误?再想想)
例子8
它只是想说如果资源不加锁的话
另一个线程可能在两个相邻的语句间去访问同一个变量,也就是说当你去查询一个线程的状态标志时
它可能己不是你查看时的那个状态了,所以你需要把标志锁起来
例子9
synchronized 去修饰方法 对所有访问某个指定对象资源的方法做同步
这样的话就不会去争用资源了
可以这样理解
同步方法先会去找资源对象 如果资源有被其它同步方法所使用则等待它们用完后还回来
如果有某个不同步的方法去占用这个资源,则即不能被同步方法发现
也不会找是否有人在用
例子10
对资源加锁(临界区),即在临界区只有一个方法能进入
synchronized(this) {
//对this做某事
}
在synchronized关键字的小括号内是要保护的资源
在synchronized关键字的大括号内是对这个资源的操作代码即:临界区
所有的方法要进入这段代码时只能排队(虚拟机会去做)
synchronized修饰方法与修饰对象都是同一个道理,
即用一定方法去保护排队使用争用的资源
修饰方法时是通过查看是否有其它的同步代码在访问(虚拟机会去做,在同步对象区排队查找)
修饰对象时则是保证这个操作的原子性(应该是通过系统的自旋锁实现)
线程四种状态
新 可运行 死 堵塞
新 即未启动
可运行 即 在就绪队列中排队等cpu分时片
堵塞 即挂起 没有在cpu分片队列中
而在堵塞队列中
死 即从run中返回了 即跑完了代码(一般是在run while循环中达到出口的条件)
yield自动放弃cpu时间片一次(下次再分过来的时候可能[有的线程做完了某件事]条件变了就不会走到这个分支,这个线程会继续运行)
suspend()
暂停但不放弃锁 resume() 取消暂停 (没做完事,在我没做完之前不能给别人处理 [占用资源 放弃处理器])
wait 等待并放弃锁
notify 通知等待进程 (没做完事,条件达不到先放弃 ,且能给别人处理[放弃资源 放弃处理器],条件合适时我再处理)