Java线程学习(一)——基础

学习JAVA多线程,对多线程的实现方式及应用做一些总结,为以后留存查看。


进程与线程

进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。

线程是指进程中的一个执行流程,一个进程中可以运行多个线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。

关于进程和线程的知识,参考阮一峰的网络日志。

对于JAVA中的线程相关知识,可以参考Java 线程简介。

JAVA线程实现

JAVA实现线程有两种方式,一是继承类:java.lang.Thread(),二是实现接口:java.lang.Runnable()。

1. 实现Runnable()接口

查看源码可知,该接口只定义了一个run()方法,实现时只需要实现run()方法即可。该方法只在指定线程启动后未停止阶段运行,如果没有将实现该接口的类作为参数来创建新的线程,则该类只在当前线程下运行。具体的说明参考Oracle的Runnable()接口说明。

public interface Runnable {
    public abstract void run();
}

简单的例子:


public class MyRunnable implements Runnable {
    
    private String name;
    
    public MyRunnable(String name) {
        this.name = name;
    }
    
    public void run() {
        System.out.println("name:" + name + " 线程ID:" + Thread.currentThread().getId());
    }
}

2. 继承Thread()类

查看源码发现,Thread()其实也是实现了Runnable()接口,也有将实现Runnable()接口的类作为参数的构造方法。具体细节,可以阅读源码或参考Oracle的Thread()类说明.

public class Thread implements Runnable {
    ......
    
    private Runnable target;
    
    ......
    
    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }
    
    ......
    
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
    ......
}

将实现Runnable()的类作为参数,另起线程:

MyRunnable runnable_1 = new MyRunnable("runnable_1");
// 实现Runnable接口,只有run()方法,没有start(),在主线程中执行
// runnable_1.run();

// 另起一个线程,runnable作为参数
new Thread(runnable_1).start();

测试

Test_1: run()和start()的异同

线程类,继承Thread()类:

class MyThread extends Thread {
    
    private String name;
    
    public MyThread(String name) {
        this.name = name;
    }
    
    @Override
    public void run() {
        System.out.println(
            "name:" + name + " ,线程ID:" + Thread.currentThread().getId() + "---时间为:" + System.currentTimeMillis());
    }
}


main()方法:

public class TestMythread {
    
    public static void main(String[] args) {
        System.out.println("主线程ID:" + Thread.currentThread().getId() + "---时间为:" + System.currentTimeMillis());

        MyThread thread_1 = new MyThread("小明");
        // 起一个新的线程执行
        thread_1.start();

        MyThread thread_2 = new MyThread("小芳");
        // run()方法会在主线程中执行,不会再起一个新线程执行
        thread_2.run();
    }
}

运行结果:


主线程ID:1---时间为:1481271550678
name:小明 ,线程ID:9---时间为:1481271550679
name:小芳 ,线程ID:1---时间为:1481271550679

结果分析:

start()方法会另起一个新的线程执行程序,执行线程的ID不一样;而run()方法是在主线程中执行程序,执行线程的ID和主线程ID一样。

Test_2: Thread()与Runnable()

实现Runnable()接口的类:

public class MyRunnable implements Runnable {
    
    private String name;
    
    public MyThread(String name) {
        this.name = name;
    }
    
    @Override
    public void run() {
        System.out.println(
            "name:" + name + " ,线程ID:" + Thread.currentThread().getId() + "---时间为:" + System.currentTimeMillis());
    }
}


main()方法:

public class TestMythread {
    
    public static void main(String[] args) {
        System.out.println("主线程ID:" + Thread.currentThread().getId() + "---时间为:" + System.currentTimeMillis());
        
        MyRunnable thread_1 = new MyRunnable("小明");
        // 实现Runnable接口,只有run()方法,没有start(),在主线程中执行
        thread_1.run();
        // 另起一个线程,runnable作为参数
        new Thread(thread_1).start();
    }
}

运行结果:


主线程ID:1---时间为:1481275074133
name:小明 线程ID:1---时间为:1481275074134
name:小明 线程ID:9---时间为:1481275074134

结果分析:

MyRunnable()类实现了Runnable()接口,重写了run()方法,在new出新的类时,调用run()方法,会在主线程中运行(线程ID相同);当该类作为参数new新的线程,调用start()方法时,就会另起一个线程运行(线程ID不同),此时如果调用新启线程的run()方法,也是在主线程中执行。

你可能感兴趣的:(Java线程学习(一)——基础)