java之多线程

1、 什么是进程?

一个进程代表一个应用程序

2、多进程有什么作用?

单进程计算机只能做一件事情。

多进程不是提高运行速度,而是体高CPU的使用率

进程和进程的内存是独立的

3、什么是线程

线程是一个进程中的执行场景。一个进程可以启动多个线程

4、多线程有什么作用

多线程不是为了提高执行速度,而是提高应用程序的使用率

线程和线程共享“堆内存和方法区内存”,栈内存是独立的,一个线程一个栈

5、java程序的运行原理

java命令会启动java虚拟机,启动JVM,等同于启动了一个应用程序,表示启动了一个

进程,该进程会自动启动一个主线程,然后主线程去调用某个类中的main方法,所以

main方法运行在主线程中,在此之前所有程序都是单线程的

举个栗子:

分析一下程序有几个线程?

class Test {
    public static void main(String[] args){
        m1();
    }
    public static void m1() {
        m2();
    }
    public static void m2() {
        m3();
    }
    public static void m3() {
        System.out.println("m3....");
    }
}

java中多线程的实现方式

在java语言中实现多线程的第一种方法:

step1、继承java.lang.Thread

step2、重写run方法

如何定义线程?
如何创建线程?
如何启动线程?

举个栗子:

class Test {
    public static void main(String[] args){
        
        //创建线程
        Thread t = new Processor();
        // 启动线程
        t.start(); // 这段代码执行瞬间结束,告诉JVM再分配一个新的栈给t线程
                   // run方法不需要程序员手动调用,系统线程启动之后自动调用run方法
        
        // 这段线程在主线程中运行
        for(int i = 0; i < 10;i++) {
            System.out.println("main -- > " + i);
        }
        // 有了多线程之厚,main方法结束只是主线程栈中没有方法栈帧了
        // 但是其他线程或者其他栈中还有栈帧
        // main方法结束,程序可能还在运行
    }
}
// 定义一个线程
class Processor extends Thread{
    // 重写run方法
    public void run() {
        for(int i = 0;i < 10; i++) {
            System.out.println("run -- > " + i);
        }
    }
}

解释如图:

JVM

java中实现线程的第二种方式:

step1、写一个类实现java.lang.Runnable接口

step2、实现run方法

class Test {
    public static void main(String[] args){
        
        //创建线程
        Thread t = new Thread(new Processor());
        // 启动线程
        t.start(); // 这段代码执行瞬间结束,告诉JVM再分配一个新的栈给t线程
                   // run方法不需要程序员手动调用,系统线程启动之后自动调用run方法
        
        // 这段线程在主线程中运行
        for(int i = 0; i < 10;i++) {
            System.out.println("main -- > " + i);
        }
    }
}
// 这种方式是推荐的,因为一个类实现接口之外保留了类的继承
class Processor implements Runnable{
    // 重写run方法
    public void run() {
        for(int i = 0;i < 10; i++) {
            System.out.println("run -- > " + i);
        }
    }
}

线程生命周期如下图:

优先级分类:最高级、标准级、最低级

优先级高的获取cpu时间片相对多一些
优先级:1-10
最低 1
最高 10
默认 5

class Test {
    public static void main(String[] args){
        
        System.out.println(Thread.MAX_PRIORITY); // 10
        System.out.println(Thread.MIN_PRIORITY); // 1
        System.out.println(Thread.NORM_PRIORITY); // 5
        
        Thread t1 = new Processor();
        t1.setName("t1");
        
        Thread t2 = new Processor();
        t1.setName("t2");
        
        System.out.println(t1.getPriority()); // 5
        System.out.println(t2.getPriority()); // 5
        // 获取优先级
        t1.setPriority(5);
        t2.setPriority(10);
        // 设置优先级
        t1.start();
        t2.start();
        
    }
}
// 这种方式是推荐的,因为一个类实现接口之外保留了类的继承
class Processor extends Thread{
    // 重写run方法
    public void run() {
        for(int i = 0;i < 10;i++) {
            System.out.println(Thread.currentThread().getName() + "-->" + i);
        }
    }
}
class Test {
    public static void main(String[] args){
        // 如何获得当前线程对象
        Thread t = Thread.currentThread(); // t保存内存地址指向的线程是”主线程对象“
        
        // 获取线程的名字
        System.out.println(t.getName()); // main
        
        Thread t1 = new Thread(new Processor());
        t1.start();
        
        Thread t2 = new Thread(new Processor());
        t2.setName("hl"); // 改名
        t2.start();
    }
}
// 这种方式是推荐的,因为一个类实现接口之外保留了类的继承
class Processor extends Thread{
    // 重写run方法
    public void run() {
        Thread t = Thread.currentThread(); // t保存的内存地址指向的线程是t1线程对象
        System.out.println(t.getName()); // Thread-0
    }
}

三个方法:

1、获取当前线程对象 Thread.currentThread();

2、给线程起名字 t.setName();

3、获取线程的名字 t.getName();

class Test {
    public static void main(String[] args){
        // 如何获得当前线程对象
        Thread t = Thread.currentThread(); // t保存内存地址指向的线程是”主线程对象“      
        Thread t1 = new Thread(new Processor());
        t1.start();
        
    }
}
// 这种方式是推荐的,因为一个类实现接口之外保留了类的继承
class Processor extends Thread{
    // 重写run方法
    public void run() {
        for(int i = 0; i < 10;i++) {
            System.out.println(Thread.currentThread().getName() + " -- >" + i);
            try {
                Thread.sleep(1000);  // 让当前线程堵塞一秒
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

一道面试题:

问下列程序是否发生堵塞

class Test {
    public static void main(String[] args){
        
        // 创建线程
        Thread t = new Processor();
        t.setName("t");
        
        t.start();// 启动线程
        
        //休眠
        try {
            t.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } // 等同于Thread.sleep(5000);堵塞的是当前线程,和t线程无关
        
        System.out.println("Hello world!");
    }
}
// 这种方式是推荐的,因为一个类实现接口之外保留了类的继承
class Processor extends Thread{
    public void run() {
        for(int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "---->" + i);
        }
    }
}

1、Thread.sleep(毫秒)
2、sleep方法是一个静态方法
3、该方法的作用,阻塞当前线程,腾出cpu,让给其它线程

class Test {
    public static void main(String[] args){
        
        // 创建线程
        Thread t = new Processor();
        t.setName("t");
        
        t.start();// 启动线程
        
        //休眠
        try {
            t.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } // 等同于Thread.sleep(5000);堵塞的是当前线程,和t线程无关
        
        System.out.println("Hello world!");
    }
}
// 这种方式是推荐的,因为一个类实现接口之外保留了类的继承
class Processor extends Thread{
    public void run() {
        for(int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "---->" + i);
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。