1.什么是线程,进程:
→:线程是操作系统能够进行运算调度的最小单位,被包含在进程之中,是进程的实际运作单位,
例子:计算机的核心是cpu,他承担了所有的计算任务,时刻在运行,而进程就好比它的车间(可以有单个,也可以是多个,根据cpu的核数决定,
这里主要说的就是单核的情况只能同时有一个车间工作),当一个车间工作的时候,其他的车间就不能够工作了。但是一个车间里面可以有好多个工人(线程),
车间里面的空间是工人们所共享的,当然也有例外,有些情况就不允许大家同时访问某些空间,比如厕所...解决方案:互斥锁,还有一些资源允许同时访问,但是要判断访问的人数和可容纳人数的关系,(信号量 机制)。
自己的例子:我们写的代码中在执行一个操作的同时需要进行另外一些操作,Ajax,异步请求!单独发的Ajax请求就是一个线程,它也属于进程(我们编写的代码)的一部分,而且也可以使用进程的资源。2018-11-17
2.如何创建一个线程:
→线程的分类:用户级线程和内核级线程
用户及线程:线程归进程管理,cpu并不知道线程的存在,在分配资源的时候是按照进程分配的,单核多核对于它并没有什么区别
内核级线程:线程归cpu管理,在分配资源的时候是按照线程数来分配资源,可以充分发挥多核的效率,但是每次线程的调用都是系统调用,代价大
组合方式:线程创建完全在用户空间中完成,线程的调度和同步也是在应用程序中进行,一个应用程序中的多个用户级线程被映射到内核级线程中(通过线程池)
→创建线程
继承thread类:
使用方法:重写run()方法,通过new 对象 .start()来创建一个新的线程
实现runable接口:内部只有一个抽象方法run()
When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
---public abstract void run();
使用方法:重写run()方法,new thread(将类作为参数传入)调用构造方法
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
作为比较看一下无参构造:
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
两者的初始化数据基本一致,只有runable参数target不同,这个参数的作用也无非就是this.target = target;对属性进行初始化。
init()方法:对thread中的一些属性进行初始化。
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();
}
start()方法:此处涉及线程的五种状态:创建,就绪,运行,阻塞,死亡
→创建:生成线程对象还没有调用start()方法
→就绪:调用start()方法,还没有运行run()方法
→运行:执行run()内部代码
→阻塞:线程执行期间被暂停
→死亡:run()结束或者调用stop()方法
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
由上可知:继承thread类和实现runable()接口实质上是一样的,所需要的只不过是自己重写的run()方法。实现了接口也不过是将重写的run()方法单独提了出来,然后再作为thread的构造方法的参数,通过init()方法进行thread对象的初始化。然后我们来看一下具体的thread.start()都做了哪些工作:调用start()方法后,会创建一个线程,准备好各项准备工作之后,调用run()方法来执行操作,另一方面主线程直接运行start()后面的代码,若直接调用run()也可以实现代码功能,只不过那样是同步执行的,就是一个普通的方法调用。
通过callable和future task创建:简单说一下吧:其实看了半天也没太懂~~~
貌似就是实现callable接口,重写call()方法, 然后调用Executors.newCacheThreadPool().submit(new 创建的对象);---有返回值 可以用Future<t> .get();获取返回值
通过线程池创建:首次要了解一下线程池的各个概念:corePoolSize,maximumPoolSize,keepAliveTime,workQueue,handler.
→corePoolSize:
→miaximumPoolSize;核心线程和非核心线程的总数
→keepAliveTime:非核心线程可以保留的最大空闲时间
→workQueue:
→handler:
线程池的执行流程:(使用者)提交任务→(线程者)核心线程数是否满→(不满)创建线程执行任务→(满)队列是否已满→(不满)将任务存储在队列中→(满)线程池是否已满→(不满)创建线程执行任务→(满)按照策略处理相应任务
→拒绝策略: abortpolicy:不执行新的任务,直接抛出异常
discardpolicy:不执行新的任务也不抛出异常
discardoldsetpolicy:将消息队列中的第一个任务替换为新任务
callerrunspolicy:直接调用execute来执行当前任务
常见的线程池:
cachedThreadPool:可缓存线程,没有核心线程,非核心线程为无限大,使用过后保留一段时间后若没有再次被使用则被回收
FixedThreadPool:定长的线程池,核心线程数即为最大线程数,没有非核心线程
SingleThreadPool:只有一条线程
schedulethreadpool:周期性线程池,核心线程数固定,且非核心线程数无限,常用于处理周期性任务
一下午就搞了这两个概念0.0,还是一知半解的,总结一下,线程和进程的大致了解,创建线程的4中方式,主要是实现callable接口有点难理解,先记得使用过程好了,之后再慢慢的体会加深理解吧。--------2018/11/17