本文共 4842 字,大约阅读时间需要 16 分钟。
本来这段时间学习的是C/C++一类的知识,知识最近看到了C一块的线程,因为是标准库函数提供的,所以理解和使用的时候其实要比java的线程相对要稍微难一点,而线程这一段,其实算是代码中相对比较难的一部分,所以想着还是把java的线程和C语言下一类的线程做一个整体性的总结学习,在两者的相互对比中,看到共同点,差异点,当然因为本人也是一个new coder,所以可能有一些总结的不对的地方,希望各位看官能够及时的指出。
对比一下程序,进程以及线程
程序:就是安装在磁盘上的一个指令集合,是一种静态的概念进程:运行中的程序,当然一个程序可能fork出很多子进程,进程算是程序的子集,她是一种动态的概念,而每个进程其实都是有自己的独立的资源
线程:又被称为轻量级的进程,也就是程序执行的最小单元,是程序中一个单一顺序控制的流程。线程是进程中的一个实体,它是被系统独立调度和分配的基本单位,也就是进程的子集
那什么有是多线程呢?
多线程:就是单个程序中可以同事运行多个不同的线程,通过这些不同的线程来执行不同的任务多线程具有的特点: 1:一个进程同时包含一个或者多个线程 2:如果一个程序需要实现多个代码同时交替运行,那么这个时候就是需要产生多个线程 3:线程本身是不具有系统资源,而是与同属一个进程的其他线程共享了所在进程所拥有的资源 4:同一个进程的多个线程能够并发执行,cpu会随机抽出时间让我们的程序选择执行不同的功能代码多线程的目的: “最大的利用Cpu”就是多线程编程的主要目的 也是就当某个线程不需要占用cpu资源的时候,让需要占用cpu资源的线程有机会获取cpu资源
1:直接使用Thread去创建或者使用自定义的Thread
当一个普通的类去继承Thread类的时候,就能通过start方法去启动线程,执行线程中的run方法Thread的子类能够实例话。但是子类中需要去掉super方法。不然可能会执行递交的task任务
2:一个类去实现Runable,然后再通过Thread去执行这个task
通过runable接口的类必须借助Thread类才能创建线程,创建一个Runable接口类实例创建一个Thread的对象,将第一步的Runable对象作为参数传入Thread中通过Thread的start方法去启动执行
直接上代码
package com.zzf.demo.thread;/** * 注意Runable其实不是线程,它只是线程执行的一个task任务。所以真正的线程其实只有thread。 * runable只是一个接口而已,而我们如果去翻看相关源码的时候,其实就可以看到,Thread的父亲其实就是Runable * @author dean * */public class MyThreadImplementsRunable implements Runnable{ @Override public void run() { // TODO Auto-generated method stub System.out.println("this is a MyCustomRunable implements Runable"); }}
package com.zzf.demo.thread;public class MyThreadExtendsThread extends Thread{ /** * 无参数的构造方法 */ public MyThreadExtendsThread() { super(); } /** * @param target 任务 * @param name 线程名字 */ public MyThreadExtendsThread(Runnable target, String name) { super(target, name); // TODO Auto-generated constructor stub } /** * @param target 执行的任务 */ public MyThreadExtendsThread(Runnable target) { super(target); // TODO Auto-generated constructor stub } /** * @param name 线程名字 * 默认任务执行是会从线程本身的run方法中进行执行 */ public MyThreadExtendsThread(String name) { super(name); // TODO Auto-generated constructor stub } /** * @param group 将线程归属到某个线程组中去 * @param target 执行的runable任务 * @param name 线程名字 * @param stackSize 栈的大小 */ public MyThreadExtendsThread(ThreadGroup group, Runnable target, String name, long stackSize) { super(group, target, name, stackSize); // TODO Auto-generated constructor stub } /** * @param group 线程组 * @param target 目标task任务 * @param name 线程名字 */ public MyThreadExtendsThread(ThreadGroup group, Runnable target, String name) { super(group, target, name); // TODO Auto-generated constructor stub } /** * @param group 线程组 * @param target 目标task */ public MyThreadExtendsThread(ThreadGroup group, Runnable target) { super(group, target); // TODO Auto-generated constructor stub } /** * @param group * @param name */ public MyThreadExtendsThread(ThreadGroup group, String name) { super(group, name); // TODO Auto-generated constructor stub } @Override public void run() { // TODO Auto-generated method stub //如果是super.run那么此时会调用runable中的方法,然后再去调自己的方法 System.out.println("this is a thread extends from thread"); } }
package com.zzf.demo.thread;public class ThreadTestMain { public static void main(String[] args) { // TODO Auto-generated method stub MyThreadImplementsRunable customRunable = new MyThreadImplementsRunable(); //向线程去递交一个执行任务, Thread thread =new Thread(customRunable); thread.start(); MyThreadExtendsThread thread2 = new MyThreadExtendsThread(); //提交的是自定义的任务先执行自己本任务,然后线程再去执行自定义的任务,所以一般情况下都是由Thread递交task任务 //一般不会去用自定义的线程来执行特殊的task任务,因为二者之间往往可能会产生一些冲突 MyThreadExtendsThread thread3 = new MyThreadExtendsThread(customRunable); //在开发的过程中建议给你的线程起一个名字,因为如果一旦遇到问题,更方便我们去定位是哪一个线程出现了问题 MyThreadExtendsThread thread4 = new MyThreadExtendsThread("myThread"); thread2.start(); thread3.start(); thread4.start(); }}
当然这只是一个小小的Demo,主要就是讲怎么去创建线程,然而我们在实际的应用过程中,可能使用的时候为了图方便。调用方式五花八门。但是最终其实还是归根到原理性的一块
如:实际调用中可能出现的不规范,这种方式如果线程内部执行出错,可能定位稍微困难:new Thread(){ public void run() { System.err.println("this is a thread"); }; }.start();
new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub System.out.println("this is a runable thread"); } }).start();
在线程的使用过程中,还有很多方法,如使用线程池去递交我们 task等。会在后续的博客中持续更新,结合javaApi以及源码的形式。
以上就是关于线程的一点简单介绍,切合的并不是太深入。有兴趣的可以去看看javaApi以及Thread的源码,其实总的来说java的线程调用等,其实是在native层去做的,翻过源码的可以看到,在Thread类中,有很多native方法。这些都是通过结合C中的线程来执行的。
转载地址:http://ewbsn.baihongyu.com/