今天写一写关于线程的东西。
线程,现代CPU调度的基本单位,有进程创建,共享进程资源。
java中的线程:Thread
先写一下线程的一个 中断 状态标识。中断标识 用来表示该线程接收到了中断请求。Thread中提供了一些方法来操作中断:
1. 向目标线程发起中断请求,则调用 目标线程 的 interrupt() 方法,该方法是实例方法
2. 查询目标线程的中断状态 isInterrupted() 方法,该方法也是实例方法
3.清除目标线程的中断状态,并返回当前目标线程的中断状态 interrupted方法,该方法是类方法。
interrupt方法 用于设置 中断
isInterrupted方法用于查询中断但不更新(不清除)中断
interrupted方法用于查询中断并更新(清除)中断
线程同步 synchronize,该关键字 可以 解决 多线程 对 同一个 资源的 竞争问题。只有 获取 到锁的 线程,才可以 执行 临界区 的 代码。
那么有一个问题: 如果 当前进入 临界区 的线程, 想释放锁该怎么办?
如果线程 想释放锁,则可以 调用 锁对象的wait()方法,该方法 会立刻释放锁。
那么还有一个问题: 如果 线程释放锁后被挂起,怎么才能唤醒呢? 则可以调用 锁对象的 notify() 方法 或者 notifyAll()方法 ,就可以唤醒了。notify调用后,会在 执行 完 synchronize 语句块内的代码 才会释放锁
前提是: 必须是 在 synchronize 内部 并且 持有 该锁对象时,才可以 调用。不然会报
Exception in thread "product" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
比如典型的 生产者消费者模式,就可以用 synchronize 和 wait/notify 来实现。
创建一个线程需要注意什么?
JDK 提供了9种创建线程对象的 构造方法:
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
Thread(Runnable target, AccessControlContext acc) {
init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
}
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
public Thread(String name) {
init(null, null, name, 0);
}
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
}
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name,
long stackSize) {
init(group, target, name, stackSize);
}
最终调用的是:
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
if (g == null) {
/* Determine if it's an applet or not */
/* If there is a security manager, ask the security manager
what to do. */
if (security != null) {
g = security.getThreadGroup();
}
/* If the security doesn't have a strong opinion of the matter
use the parent thread group. */
if (g == null) {
g = parent.getThreadGroup();
}
}
/* checkAccess regardless of whether or not threadgroup is
explicitly passed in. */
g.checkAccess();
/*
* Do we have the required permissions?
*/
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted();
this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
/* Set thread ID */
tid = nextThreadID();
}
1. 线程名字 name
2. 线程组 group, 继承 父线程的线程组
3. 是否守护线程 daemon , 继承父线程
4.优先级 priority , 继承父线程
5. 类加载器 contextClassLoader, 继承 父线程
6. Runnable 实现类 target
7. 继承父类已有的 ThreadLocalMap inheritableThreadLocals 的数据
8 线程ID
可以看到,很多属性都是继承父类的。