两篇文章了解进程与线程( 基础篇 )

一、进程:

1. 进程概念:

程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。而进程是程序在处理机上的一次执行过程,他是一个动态的概念。

进程是一个具有独立功能的程序,一个实体,每一个进程都有它自己的地址空间。

2. 进程的状态:

进程执行时的间断性,决定了进程可能具有多种状态。

1) 就绪状态(Ready)

2) 运行状态(Running)

3) 阻塞状态(Blocked)

二、线程:

1. 线程的概念:

线程实际上是在进程的基础之上的进一步划分,一个进程启动后,里面的若干个程序由可以划分成若干个线程。线程:是进程的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行,一个进程最少有一个线程,这个情况叫单线程程序。

并行:两个任务同时运行(多个CPU)

并发:两个任务同时请求运行,而处理器一次性只能接受一个任务,就会把两个任务安排轮流执行,由于CPU时间片运行较短就会感觉在一起执行。

三、线程的基本使用:

在JAVA中如果要实现多线程的操作,有两种实现方法:

1. 继承Thread类:

public class ThreadDemo {
    public static void main(String[] args) {
        new MyThread().start();//启动线程
    }
}
// 继承实现线程
class MyThread extends Thread{
    @Override
    public void run() {
        super.run();
        for (int i = 0; i < 50 ; i++) {
            System.out.println("当前执行:"+i);
        }
    }
}

2. 实现Runnable接口:

public class ThreadDemo {
    public static void main(String[] args) {
       new Thread(new MyRunnableThread()).start();//启动线程
        // 启动实现Runnable的第二种方式
        new MyRunnableThread().run();
    }
}
class MyRunnableThread implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 50 ; i++) {
            System.out.println("当前执行:"+i);
        }
    }
}

 一般推荐使用第二种实现接口的方法,第一种继承是创建一个线程,第二种是创建一个线程的执行方法,使用的是实现方法,所以还可以继承其他的类,可扩展性较强。

四、线程的休眠:

    public static void sleep(long millis, int nanos)
    throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        sleep(millis);
    }

上面是Thread中的一个方法,这个方法使当前正在执行的线程以指定的毫秒数暂停,释放CPU的时间片,具体取决于系统定时器和调度程序的精度和准确性。线程不会丢失任何显示器的所有权。

传递参数:millis 以毫秒为单位,nanos 纳秒。方法加入参数二纳秒,可以使时间更精确。

异常:InterruptedException 如果任何线程中断当前线程。则抛出异常,同时清除当前线程的中断状态。IllegalArgumentException 纳秒超出999999范围或者毫秒为负数。

// 继承实现线程
class MyThread extends Thread {
    @Override
    public void run() {
        super.run();
        for (int i = 0; i < 50 ; i++) {
            try {
                Thread.sleep(1000);
                //使用纳秒和可精确
                //Thread.sleep(10000,1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("当前执行:"+i);
        }
    }
}

五、JOIN与中断线程:

1. JOIN:

    public final synchronized void join(long millis, int nanos)
    throws InterruptedException {

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        join(millis);
    }

 等待这个线程死亡。通俗的说就是那个线程调用了他,就直接到这个线程方法执行完为止。

参数异同和上面sleep一样。

public class ThreadDemo {
    public static void main(String[] args) {

        Thread thread = new Thread(new MyRunnableThread());thread.start();


        for (int i = 0; i < 50 ; i++) {
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("主线程当前执行:"+i);
            // 当主线程执行到20时,任务线程进行JOIN
            if (i == 20){
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}
class MyRunnableThread implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 50 ; i++) {
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("MyRunnableThread当前执行:"+i);
        }
    }
}

效果:

如图可知,就是让调用的任务线程执行完毕,再执行主线程。如果未加入JOIN,共同进行执行(谁抢到就先执行谁)。 

2. 中断(Interrupt):

 public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }
 public boolean isInterrupted() {
        return isInterrupted(false);
    }
 public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }

interrupt() 方法中断这个线程,除非当前线程中断自身,这是始终允许的。

isInterrupted() 测试当前线程是否中断,该方法可以清除线程的中断状态。通俗的说,如果这个方法被两次调用,那么第二次调用则会返回false,除非当前线程再次中断,在第一个调用已经清除其中断状态之后,第二个调用之前已经经过检查。忽略线程中断,因为线程在中断时不存在将该方法返回false。

public class ThreadDemo {
    public static void main(String[] args) {

        Thread thread = new Thread(new MyRunnableThread());thread.start();


        for (int i = 0; i < 50 ; i++) {
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("主线程当前执行:"+i);
            // 当主线程执行到20时,任务线程进行JOIN
            if (i == 20){
                    thread.interrupt();

            }
        }

    }
}
class MyRunnableThread implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 50 ; i++) {
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("MyRunnableThread当前执行:"+i);
        }
    }
}

抛出了异常,sleep 中断了。做了一个中断的状态。真正中断得现场自己来中断。如果想要它真正中断,得用如下方法:

public class ThreadDemo {
    public static void main(String[] args) {

        Thread thread = new Thread(new MyRunnableThread());thread.start();


        for (int i = 0; i < 50 ; i++) {
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("主线程当前执行:"+i);
            // 当主线程执行到20时,任务线程进行JOIN
            if (i == 20){
                    thread.interrupt();
            }
        }

    }
}
class MyRunnableThread implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 50 ; i++) {
            if (Thread.interrupted()){
                break;// 如果处于中断状态,则break
            }
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
                Thread.currentThread().interrupt();// 中断当前线程
            }
            System.out.println("MyRunnableThread当前执行:"+i);
        }
    }
}

中断状态被捕捉后,中断线程。

原本想把线程的知识点写在一篇文章里,发现文章写的太长了,不方便阅读,所以将分为基础篇和进阶篇,进阶篇将会根据源码介绍 守护线程的优先级、线程同步、线程死锁、生产者与消费者的概念。 

发布了72 篇原创文章 · 获赞 152 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/qq_37857921/article/details/105230175