第二十七节(多线程、线程的创建和启动、生命周期、调度、控制、同步)

 线程指进程中的一个执行场景,也就是执行流程,那么进程和线程的区别是什么
1. 每个进程是一个应用程序,都有独立的内存空间

2. 同一个进程中的线程共享其进程中的内存和资源
(共享的内存是堆内存和方法区内存,栈内存不共享,每个线程有自己的)

什么是进程?

一个进程对应一个应用程序。 例如:在 windows 操作系统启动 Word 就表示启动了一个进程。在 java 的开发环境下启动 JVM,
就表示启动了一个进程。现代的计算机都是支持多进程的,在同一个操作系统中,可以同时启动多个进程。
/*
    分析一下程序有几个线程

        只有一个线程,就是主线程

        main,m1,m2,m3 这四个方法在同一个栈空间中

        没有启动其他任何线程

*/
public class ThreadTest01{

    public static void main(String[] args){
        ming01();
    }

    public static void arry01(){
        ming2();
    }

    public static void arry02(){
        ming03();
    }

    public static void arry03(){
        System.out.println("电子科技大学中山学院");
    }

}
/*
    在Java语言中实现多线程第一种方式:

        1. 继承java.lang.Thread
        2. 重写run方法

    三个知识点:

        定义线程
        创建线程
        启动线程

*/
public class ThreadTest02{

    public static void main(String[] args){

        // 创建一个线程
        Thread t = new Student();

        // 启动线程
        t.start();
        // start方法执行完瞬间结束,告诉JVM再分配一个新的线程 给t线程

        // run 不需要手动调用的,系统线程启动之后会自动调用run方法
        // 是随机分配的,没有规律

        // t.run(); 这是普通方法的调用,这样做程序只有一个线程,run方法结束之后,下边的程序才能继续运行

        for(int i = 0; i < 5; i++){
            System.out.println("main---------: "+i);
        }

        /*
            有了多线程之后,main方法结束只是主线程中没有方法栈帧了
            但是其他线程或者其他栈中还有栈帧
            main方法结束,程序可能还在运行
        */

    }

}

class Student extends Thread{

    // 重写run方法
    public void run(){
        for(int i = 0; i < 10; i++){
            System.out.println("run: " + i);
        }

    }

}
/*
    Java中实现多线程的第二种方法:

        1. 写一个类实现
        2. 实现run方法

*/
public class ThreadTest03{

    public static void main(String[] args){

        // 创建线程
        Thread t = new Thread(new Teacher());

        // 启动
        t.start();

    }
}

// 这种方法是推荐的,因为一个类实现接口之外保留了 类的继承
class Teacher implements Runnable {
    // 重写run方法
    public void run(){
        for(int i = 0; i < 10; i++){
            System.out.println("run: " + i);
        }

    }
}
/*
    掌握线程方法:
        1. 获取当前线程的对象 currentThread
        2. 给线程起名 t.setName("名称");
        3. 获取线程的名字:t.getName();

*/
public class ThreadTest04{

    public static void main(String[] args){

        // 获取当前线程对象 main 主线程
        Thread t = Thread.currentThread();
        // 获取线程的名称
        System.out.println("线程的名称:"+t.getName());//输出main

        Thread t1 = new Thread(new MingTest());
        // 给线程起名
        t1.setName("Ming");

        t1.start();

        Thread t2 = new Thread(new MingTest());
        // 给线程重命名
        t2.setName("中山学院");

        t2.start();

    }

}

class MingTest implements Runnable{

    public void run(){
        Thread t =     Thread.currentThread();
        System.out.println("线程名称:"+t.getName());

    }

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

    优先级:1 - 10

    优先级高的线程 会得到CPU的时间多一些,优先执行完成

*/
public class ThreadTest05{

    public static void main(String[] args){

        System.out.println("最高:" + Thread.MAX_PRIORITY);
        System.out.println("最小:" + Thread.MIN_PRIORITY);
        System.out.println("默认:" + Thread.NORM_PRIORITY);

        Thread t1 = new Keke();
        t1.setName("t1");

        Thread t2 = new Keke();
        t2.setName("t2");        

        // 都是 5
        System.out.println("t1优先级:" + t1.getPriority());
        System.out.println("t2优先级:" + t2.getPriority());

        // 设置优先级
        t1.setPriority(6);
        t2.setPriority(3);

        // 启动
        t1.start();
        t2.start();

    }

}

class Keke extends Thread{

    public void run(){
        for(int i = 0 ; i < 5; i++){
            System.out.println(Thread.currentThread().getName() + "----------- : " + i);
        }
    }

}
/*
    Thread.sleep(); 让当前正在执行的线程休眠(暂停执行)
    sleep 方法是一个静态方法
    该方法的作用:阻塞当前线程,腾出CPU,让给其他线程
*/
public class ThreadTest06{

    public static void main(String[] args){

        Thread t1 = new Ming();
        t1.setName("t1");
        t1.start();

        // 获取当前线程对象 main 主线程
        Thread t = Thread.currentThread();
        // 获取线程的名称
        System.out.println("线程的名称:"+t.getName());//输出main

        // 阻塞主线程
        for(int i = 0; i < 20; i++){
            System.out.println(Thread.currentThread().getName() + "----------- : " + i);
            try{
                Thread.sleep(1000);
            } catch(InterruptedException e){
                e.printStackTrace();
            }
        }

    }

}

class Ming extends Thread{

    public void run(){
        System.out.println("线程正在启动中.......");
        for(int i = 0; i < 20; i++){
            System.out.println(Thread.currentThread().getName() + "----------- : " + i);
            try{
                Thread.sleep(2000); // 让当前程序阻塞2S
            } catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    }

}

//输出main跟ti是随机的 
/*
    Thread.yield(); 暂停当前正在执行的线程对象,并执行其他线程。 

    1. 该方法是一个静态方法
    2. 作用: 给同一个优先级的线程让位,但是让位时间不固定
    3. 和sleep方法相同,就是yield时间不固定

    他与sleep类似,只是不能由用户指定暂停多长时间,并且yield()只能让 同优先级的线程有执行的机会

*/
public class ThreadTest08{

    public static void main(String[] args){

        // 创建线程
        Thread t = new Ming5();
        t.setName("t");

        // 启动线程
        t.start();

        // 主线程
        for(int i = 0; i < 20; i++){
            System.out.println(Thread.currentThread().getName()+"------- "+i);
        }
        System.out.println("Ming帅了 !");

    }

}

class Ming5 extends Thread{

    public void run(){
        for(int i = 0; i < 10; i++){
            System.out.println(Thread.currentThread().getName()+"------- "+i);
            if(i % 2 == 0){
                Thread.yield();
            }
        }
    }

}
/*
    线程的合并

*/
public class ThreadTest09{

    public static void main(String[] args){

            Thread t = new Thread(new Arry6());
            t.setName("t");
            t.start();

            try{
                // 合并线程
                t.join(); // t 和 主线程合并,单线程的程序
            } catch(InterruptedException e){
                e.printStackTrace();
            }

            System.out.println("---------main end--------");

            // 主线程
            for(int i = 0; i < 10; i++){
                System.out.println(Thread.currentThread().getName()+"------- "+i);
            }

        // 当前线程可以调用第一个线程的join方法,调用后当前线程会被阻塞不再执行,
        // 直到被调用的线程执行完毕,当前线程才会执行

    }

}

class Arry6 implements Runnable{

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

}
时间: 2024-10-26 08:47:27

第二十七节(多线程、线程的创建和启动、生命周期、调度、控制、同步)的相关文章

Java语言基础-多线程-①线程的创建和启动

简单阐释进程和线程 对于进程最直观的感受应该就是“windows任务管理器”中的进程管理: (计算机原理课上的记忆已经快要模糊了,简单理解一下):一个进程就是一个“执行中的程序”,是程序在计算机上的一次运行活动.程序要运行,系统就在内存中为该程序分配一块独立的内存空间,载入程序代码和资源进行执行.程序运行期间该内存空间不能被其他进程直接访问.系统以进程为基本单位进行系统资源的调度和分配.何为线程?线程是进程内一次具体的执行任务.程序的执行具体是通过线程来完成的,所以一个进程中至少有一个线程.回忆

多线程--线程的创建与启动

创建一个线程,Java提供三种方法 (1)通过实现Runnable接口,重写run方法 (2)通过继承Thread类本身,--必须重写 (3)通过Callable和Future创建线程 Thread类的方法 void start()使该线程开始执行,Java虚拟机调用该线程的run方法. final void setName(String name)改变线程名称,使之与参数name相同 setPriority(int priority)更改线程的优先级 join(long millisec)等待

centos samba/squid 配置 第二十七节课

centos  samba/squid 配置  第二十七节课 上半节课 下半节课 一. samba配置1. 什么是sambaSamba服务类似于windows上的共享功能,可以实现在Linux上共享文件,windows上访问,当然在Linux上也可以访问到.是一种在局域网上共享文件和打印机的一种通信协议,它为局域网内的不同计算机之间提供文件及打印机等资源的共享服务. 注意:smb侦听端口:139  和  445  端口 2. 安装配置samba yum install -y samba samb

Java线程:创建与启动

Java线程:创建与启动 一.定义线程 1.扩展java.lang.Thread类. 此类中有个run()方法,应该注意其用法: public void run() 如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法:否则,该方法不执行任何操作并返回.   Thread 的子类应该重写该方法. 2.实现java.lang.Runnable接口. void run() 使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独

03_线程的创建和启动_实现Runnable接口方式

[线程的创建和启动的步骤(实现Runnable接口方式)] 1.定义Runnable接口的实现类,并重写其中的run方法.run()方法的方法体是线程执行体.class SonThread  implement Runnable{ public void run(){......}} 2.创建Runnable接口实现类的实例.   sonThread s1=new SonThread(); 3.用该实例作为Thread的target来创建Thread对象.   Thread t1 =new Th

【WPF学习】第二十六章 Application类——应用程序的生命周期

原文:[WPF学习]第二十六章 Application类--应用程序的生命周期 在WPF中,应用程序会经历简单的生命周期.在应用程序启动后,将立即创建应用程序对象,在应用程序运行时触发各种应用程序事件,你可以选择监视其中的某些事件.最后,当释放应用程序对象时,应用程序将结束. 一.创建Application对象 使用Application类的最简单方式是手动创建它.下面的示例演示了最小的程序:在应用程序入口(Main()方法)处创建名为MainWindow的窗口,并启动一个新的应用程序: 在本质

02_线程的创建和启动_继承Thread方式

[简述] java使用Thread类代表线程,所有的线程都必须是Thread或者其子类的实例. 每个线程的任务就是完成一定的任务,实际上就是执行一段程序流. [创建并启动多线程的步骤(集成Thread类方式)] 1.定义继承Thread类的子类,重写run方法:run()方法就代表了线程需要完成的任务,故run()方法称为:线程执行体. 2.创建线程对象:即创建Thread子类的实例. 3.启动线程:调用线程对象的start()方法来. [示例代码FirstThread.java] packag

线程的生命周期以及控制线程

一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就绪状态(runnable). 注意:不能对已经启动的线程再次调用start()方法,否则会出现java.lang.IllegalThreadStateException异常. 2.就绪状态 处于就绪状态的线程已经具备了运行条件,但还没有分配到CPU,处于线程就绪队列(尽管是采用队列形式,事实上,把它

线程的生命周期和控制

一.线程的生命周期 进程与线程一样,都具有一定的生命周期,线程的生命周期包括四个状态:创建状态.就绪状态.阻塞状态.死亡状态. 1.创建状态 1)是指使用new实例化一个线程对象,但该线程对象还未使用start()方法启动线程这个阶段,该阶段只在内存的堆中为该对象的实例变量分配了内存空间,但线程还无法参与抢夺CPU的使用权: 2)创建完毕线程对象后,启动该线程对象的是start()方法,而不是run()方法. 2.就绪状态 1)是指一个线程对象使用start()方法后到运行完run()方法的这个

C#多线程的用法2-线程的生命周期

对于线程而言有两种类型:前台线程,后台线程.前台与后台线程性质相同,但终止条件不同. 后台线程:在运行过程中如果宿主进程结束,线程将直接终止执行:在强制终止时,线程即终止执行不论线程代码是否执行完毕. 前台线程:在运行过程中如果宿主进程结束,线程将继续执行直至线程代码执行完毕:在强制终止时,线程即结束不论线程代码是否执行完毕. 后台线程生命周期: 上图显示:只要宿主进程结束,后台线程必定结束 上图显示:后台线程功能执行完毕或被强行终止即进入结束状态,此时宿主进程并未结束 ------------