并发与并行、进程,线程调度自行百度

线程(thread):是一个进程中的其中一条执行路径,CPU调度的最基本调度的单位。同一个进程中线程可以共享一些内存(堆、方法区),每一个线程又有自己的独立空间(栈、程序计数器)。因为线程之间有共享的内存,在实现数据共享方面,比较方便,但是又因为共享数据的问题,会有线程安全问题。

当运行Java程序时,其实已经有一个线程了,那就是main线程。

Thread类

所有的线程对象都必须是Thread类或其子类的实例,Java中通过继承Thread类来创建启动多线程的步骤如下:

  1. 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。

  2. 创建Thread子类的实例,即创建了线程对象

  3. 调用线程对象的start()方法来启动该线程

Runnable接口

我们还可以实现Runnable接口,重写run()方法,然后再通过Thread类的对象代理启动和执行我们的线程体run()方法。步骤如下:

  1. 定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。

  2. 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正 的线程对象。

  3. 调用线程对象的start()方法来启动线程。

例: public class MyRunnable implements Runnable  //定义实现线程类

    MyRunnable mr = new MyRunnable();     //创建线程对象

         Thread t = new Thread(mr);         //通过Thread类的实例,启动线程
          t.start();

实际上所有的多线程代码都是通过运行Thread的start()方法来运行的。因此,不管是继承Thread类还是实现 Runnable接口来实现多线程,最终还是通过Thread的对象的API来控制线程的,熟悉Thread类的API是进行多线程编程的基础。

tips:Runnable对象仅仅作为Thread对象的target,Runnable实现类里包含的run()方法仅作为线程执行体。 而实际的线程对象依然是Thread实例,只是该Thread线程负责执行其target的run()方法。

两种方式的区别

1、继承的方式有单继承的限制,实现的方式可以多实现

2、启动方式不同

3、继承:在实现共享数据时,可能需要静态的

  实现:只要共享同一个Runnable实现类的对象即可。

4、继承:选择锁时this可能不能用,

  实现:选择锁时this可以用。

匿名内部类对象来实现线程的创建和启动

new Thread("新的线程!"){
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName()+":正在执行!"+i);
}
}
}.start();

构造方法

public Thread() :分配一个新的线程对象。

public Thread(String name) :分配一个指定名字的新的线程对象。

public Thread(Runnable target) :分配一个带有指定目标新的线程对象。

public Thread(Runnable target,String name) :分配一个带有指定目标新的线程对象并指定名字。

线程常用方法

volatile:修饰变量

变量不一定在什么时候值就会被修改了,为了总是得到最新的值,volatile修饰之后那么每次都从主存中去取值,不会在寄存器中缓存它的值。

守护线程

守护线程有个特点,就是如果所有非守护线程都死亡,那么守护线程自动死亡。

调用setDaemon(true)方法可将指定线程设置为守护线程。必须在线程启动之前设置,否则会报IllegalThreadStateException异常。

调用isDaemon()可以判断线程是否是守护线程。