26.JAVA编程之进程与线程

1.什么是进程

程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。而进程是程序在处理机上的一次执行过程,它是一个动态的概念。
进程是一个具有一定独立功能的程序,一个实体,每一个进程都有它自己的地址空间。

2.进程的状态

进程执行时的间断性,决定了进程可能具有多种状态。事实上,运行中的进程具有以下三种基本状态。
就绪状态、运行状态、阻塞状态

3.什么是线程

线程实际上是在进程基础上的进一步划分,一个进程启动之后,里面的若干程序又可以划分成若干线程。
线程是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行,一个进程最少有一个线程(单线程程序)
一个程序可以同时执行多个任务,来提高效率。例如:同时下载多个电影、同时与多人聊天
并行:两个任务同时运行(多个CPU)
并发:两个任务同时请求运行,而处理器一次只能接受一个任务,就会把两个任务安排轮流执行,由于CPU时间片运行时间较短,就会感觉两个任务在同时执行。

4.线程的基本使用

方法一:继承Thread类

public class Demo2 {
    public static void main(String[] args) {
        MyThread mt = new MyThread();
        mt.start(); //启动线程
    }
}

class MyThread extends  Thread{
    @Override
    public void run() {
        for (int i = 0; i <50 ; i++) {
            System.out.println("");
        }
    }
}

运行效果:

方法二:实现Runnable接口

public class Demo2 {
   public static void main(String[] args) {
       MyRunnable mr = new MyRunnable();
       Thread t2 = new Thread(mr);
       t2.start();
   }
}

class MyRunnable implements Runnable{
   @Override
   public void run() {
       for (int i = 0; i <50 ; i++) {
           System.out.println(Thread.currentThread().getName()+"-"+i);
       }
   }
}

更加推荐使用第二种方法,实现Runnable接口创建多线程与继承Thread类相比优点是:

1.避免了继承Thread类的单继承的局限性。

【类只能单继承,类继承了Thread类就不能继承其他的类

而实现了Runnable接口,还可以继承其他的类,实现其他的接口

2.实现Runnable接口降低了线程对象和线程任务的耦合性,增强了程序的可扩展性。

【实现Runnable接口的方式,把设置线程任务和开启新线程进行了分离(实现解耦)

实现类中,重写了run方法来设置线程任务

创建Thread类对象,调用start方法来开启新线程

创建Thread类对象,构造方法中传递Runnable接口的实现类对象,可以传递不同的实现类(可扩展性)

3.实现Runnable接口将线程单独进行对象的封装,更符合面向对象思想。

参考:多线程之实现Runnable接口及其优点 - 初仰 - 博客园

5.线程的休眠

在当前线程的执行中,暂停指定的毫秒数,释放CPU的时间片
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
示例代码:

public class Demo2 {
    public static void main(String[] args) {
        MyThread mt = new MyThread();
        MyRunnable mr = new MyRunnable();
        Thread t2 = new Thread(mr);

        mt.start(); //启动线程
        t2.start();
    }
}

class MyThread extends  Thread{
    @Override
    public void run() {
        for (int i = 0; i <50 ; i++) {
            System.out.println(Thread.currentThread().getName()+"-"+i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i <50 ; i++) {
            System.out.println(Thread.currentThread().getName()+"-"+i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

运行效果:

6.线程的一些函数

Thread.currentThread():返回对当前正在执行的线程对象的的引用
Thread.currentThread().getName():获取当前线程的名称

7.join与中断线程

1.join

public final void join() throws InterruptedException:等待这个线程死亡,调用此方法的行为方式与调用完全相同。

join:加入线程,让调用的线程先执行指定时间或执行完毕。

异常 InterruptedException:如果任何线程中断当前线程,当抛出此异常时,当前线程的中断状态将被清除。

public class ThreadDemo2 {

public static void main(String[] args) {

MyRunnable2 mr2 =new MyRunnable2();

        Thread t =new Thread(mr2);

        t.start();

        for (int i =0; i <50; i++) {

System.out.println(Thread.currentThread().getName() +"-"+i);

            try {

Thread.sleep(300);

            }catch (InterruptedException e) {

e.printStackTrace();

            }

if(i==20)

{

try {

t.join(); //让t线程执行完毕,再执行main

                }catch (InterruptedException e) {

e.printStackTrace();

                }

}

}

}

}

class MyRunnable2implements Runnable {

@Override

    public void run() {

for (int i =0; i <50; i++) {

System.out.println(Thread.currentThread().getName() +"-"+i);

            try {

Thread.sleep(300);

            }catch (InterruptedException e) {

e.printStackTrace();

            }

}

}

}

执行结果:main线程和t线程开始一起执行,在main线程执行到20时,t线程一个人执行,待t线程执行完毕之后再开始执行main线程。

运行效果:

2.中断线程

方法一:使用interrupt方法来中断线程,设置一个中断状态(标记),需要注意sleep等方法会清除标记,需要相应的处理才能实现中断。
此方法需要修改三处代码,需要写判断,不推荐使用。
public void interrupt():

异常 InterruptedException:如果任何线程中断当前线程,当抛出此异常时,当前线程的中断状态将被清除。

public class ThreadDemo2 {

public static void main(String[] args) {

MyRunnable2 mr2 =new MyRunnable2();

        Thread t =new Thread(mr2);

        t.start();

        for (int i =0; i <50; i++) {

System.out.println(Thread.currentThread().getName() +"-"+i);

            try {

Thread.sleep(300);

            }catch (InterruptedException e) {

e.printStackTrace();

            }

if(i==20)

{

t.interrupt();  //中断线程,只是做了一个中断标记,

            }

}

}

}

class MyRunnable2implements Runnable {

@Override

    public void run() {

for (int i =0; i <50; i++) {

if(Thread.interrupted())//测试中断状态,此方法会把中断状态清除

            {

break;

            }

System.out.println(Thread.currentThread().getName() +"-"+i);

            try {

Thread.sleep(300);

            }catch (InterruptedException e) {

e.printStackTrace();

                Thread.currentThread().interrupt();

            }

}

}

}

运行效果:



方法二:自定义标记的方式,更好控制,更加推荐使用。

public class ThreadDemo2 {

public static void main(String[] args) {

MyRunnable3 mr3 =new MyRunnable3();

        Thread t2 =new Thread(mr3);

        t2.start();

        for (int i =0; i <50; i++) {

System.out.println(Thread.currentThread().getName() +"-"+i);

            try {

Thread.sleep(300);

            }catch (InterruptedException e) {

e.printStackTrace();

            }

if(i==20)

{

mr3.flag =false;

            }

}

}

}

class MyRunnable3implements Runnable{

public boolean flag =true;

    //构造方法

    public MyRunnable3()

{

flag =true;

    }

@Override

    public void run() {

int i =0;

        while (flag)

{

System.out.println(Thread.currentThread().getName()+"-"+(i++));

            try {

Thread.sleep(300);

            }catch (InterruptedException e) {

e.printStackTrace();

            }

}

}

}

运行效果:


7.守护线程

public class ThreadDemo2 {

    public static void main(String[] args) {
        MyRunnable3 mr3 = new MyRunnable3();
        Thread t2 = new Thread(mr3);
        t2.setDaemon(true);
        t2.start();

        for (int i =0; i <50; i++) {
            System.out.println(Thread.currentThread().getName() +"-"+i);
            try {
                Thread.sleep(200);
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class MyRunnable3 implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            System.out.println(Thread.currentThread().getName()+"-"+i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

    }
}

运行效果:
主线程运行结束之后,设置为守护线程的t线程也结束了。


8.其他方法与优先级

getId():返回该线程的标志符
getName():返回该线程的名称
setName():改变线程的名称
isAlive():测试线程是否处于活动状态
setPriority(int newPriority):更改线程优先级,可选MAX_PRIORITY、MIN_PRIORITY/NORM_PRIORITY

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。