Java复习与学习笔记----进程和线程与同步(上)

简介: Java复习与学习笔记----进程和线程与同步

进程

进程:是正在运行的程序

是系统进行资源分配和调用的独立单位

每一个进程都有它自己的内存空间和系统资源

线程

线程:是进程中的单个顺序控制流,是一条执行路径

单线程:一个进程如果只有一条执行路径,称为单线程程序

多线程:一个进程如果有多条执行路径,称为多线程程序

多线程的实现方式

方式一:继承 Thread 类

定义一个类 MyThread 继承 Thread 类

在MyThread 类中重写run()方法

创建MyThread类的对象

启动线程

//**方式一:继承 Thread 类**
//        定义一个类 MyThread 继承 Thread 类
//        在MyThread 类中重写run()方法
//        创建MyThread类的对象
//        启动线程
public class MyThread extends Thread {
    @Override
    public void run() {
        for ( int i=0; i<100; i++ ) {
            System.out.println( this.getName() + " " + i );
        }
    }
    //重写run方法,run方法是用来封装被线程执行的代码
}
public class Test {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();//启动线程
        //调用run方法只是单纯调用方法,没有启动线程
        //调用start方法会导致线程开始执行,Java会调用此线程的run方法
    }
}

run方法封装线程执行的代码,直接调用,相当于普通方法的调用

start方法启动线程,然后由JVM调用此线程的run方法

设置和获取线程的名称

Thread类中设置和获取线程名称的方法:

void setName( String name ) : 将此线程的名称改为等于参数name

String getName() : 返回此线程的名称

public class Test {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.setName("我的线程");
        System.out.println(myThread.getName());
    }
}
输出:
我的线程
public class Test {
    public static void main(String[] args) {
        //Thread.currentThread()返回对当前正在执行的线程对象的引用
        System.out.println( Thread.currentThread() );
    }
}
输出:
Thread[main,5,main]

通过构造方法设置线程的名称:

public class MyThread extends Thread {
    public MyThread() {
    }
    public MyThread(String name) {
        super(name);
    }
    @Override
    public void run() {
        for ( int i=0; i<100; i++ ) {
            System.out.println( this.getName() + " " + i );
        }
    }
}
public class Test {
    public static void main(String[] args) {
        MyThread myThread = new MyThread("我的线程");
        System.out.println( myThread.getName() );
    }
}
输出:
我的线程

线程调度

线程有两种调度模式:

分时调度模型:所有线程轮流使用CPU的使用权。平均分配每个线程占用CPU的时间片

抢占式调度模式:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么随机选择一个,优先级高的线程获取的CPU时间片相对多一些

Java使用的是抢占式模式调度

多线程执行具有随机性,因为谁抢到CPU的使用权不一定

Thread 类中设置和获取线程优先级的方法:

public final int getPriority(): 返回此线程的优先级

public final void setPriority( int newPriority ):更改此线程的优先级

线程的优先级具有范围:1-10,默认优先级为5

public class Test {
    public static void main(String[] args) {
        MyThread myThread1 = new MyThread();
        System.out.println(myThread1.getPriority());
        MyThread myThread2 = new MyThread();
        myThread2.setPriority(10);
        MyThread myThread3 = new MyThread();
        myThread3.setPriority(1);
        System.out.println(myThread2.getPriority());
        System.out.println(myThread3.getPriority());
    }
}
输出:
5
10
1
System.out.println(Thread.MAX_PRIORITY);
System.out.println(Thread.MIN_PRIORITY);
输出:
10
1

线程优先级高仅仅表示获取CPU时间片的几率高,并不是优先级高的线程一定每次都可以抢到CPU时间片

线程控制

sleep
public class MyThread extends Thread {
    public MyThread() {
    }
    public MyThread(String name) {
        super(name);
    }
    @Override
    public void run() {
        for ( int i=0; i<100; i++ ) {
            System.out.println( this.getName() + " " + i );
            try {
                Thread.sleep(1000);//线程休眠一秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
join
public class Test {
    public static void main(String[] args) {
        MyThread myThread1 = new MyThread();
        MyThread myThread2 = new MyThread();
        MyThread myThread3 = new MyThread();
        myThread1.start();
        try {
            myThread1.join();//线程一执行完成才会执行后面其他线程
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        myThread2.start();
        myThread3.start();
    }
}
setDaemon
public class Test extends Thread {
    public static void main(String[] args) {
        MyThread myThread1 = new MyThread();
        MyThread myThread2 = new MyThread();
        myThread1.setDaemon(true);
        myThread2.setDaemon(true);
        myThread1.start();
        myThread2.start();
        Test test = new Test();
        test.start();
        //当test执行结束,剩下的线程都为守护线程,会直接退出
    }
    @Override
    public void run() {
        for ( int i=0; i<10; i++ ) {
            System.out.println( "main" + " " + i );
        }
    }
}
public class MyThread extends Thread {
    @Override
    public void run() {
        for ( int i=0; i<100; i++ ) {
            System.out.println( this.getName() + " " + i );
        }
    }
}

线程的生命周期

多线程的实现方式二

创建线程的另一种方法:声明一个实现Runnable接口的类,实现run方法。然后可以分配类的实例,在创建Thread时作为参数传递,并启动线程。

实现多线程的方法二:

1.定义一个MyRunnable类实现Runnable接口

2.在MyRunnable类中重写run方法

3.创建MyRunnable类的对象

4.创建Thread类的对象,把MyRunnable对象作为构造方法的参数

5.启动线程

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for ( int i=0; i<10; i++ ) {
            System.out.println( i );
        }
    }
}
public class Test {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}

给线程设置名字

thread.setName("我的线程");
System.out.println(thread.getName());

在创建线程对象时,给线程设置名字

Thread thread = new Thread(myRunnable, "我的线程~~");
        System.out.println(thread.getName());

多线程的实现方案:

1.继承Thread类

2.实现Runnable接口

相对于继承Thread类,实现Runnable接口,避免了Java单继承的局限性,适合多个相同程序的代码处理同一个资源的情况,把线程和程序的代码、数据有效分离,较好的体现了面向对象的设计思想


相关文章
|
2天前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
33 14
|
5天前
|
安全 Java 程序员
Java 面试必问!线程构造方法和静态块的执行线程到底是谁?
大家好,我是小米。今天聊聊Java多线程面试题:线程类的构造方法和静态块是由哪个线程调用的?构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节有助于掌握Java多线程机制。下期再见! 简介: 本文通过一个常见的Java多线程面试题,详细讲解了线程类的构造方法和静态块是由哪个线程调用的。构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节对掌握Java多线程编程至关重要。
34 13
|
6天前
|
安全 Java 开发者
【JAVA】封装多线程原理
Java 中的多线程封装旨在简化使用、提高安全性和增强可维护性。通过抽象和隐藏底层细节,提供简洁接口。常见封装方式包括基于 Runnable 和 Callable 接口的任务封装,以及线程池的封装。Runnable 适用于无返回值任务,Callable 支持有返回值任务。线程池(如 ExecutorService)则用于管理和复用线程,减少性能开销。示例代码展示了如何实现这些封装,使多线程编程更加高效和安全。
|
1月前
|
缓存 安全 算法
Java 多线程 面试题
Java 多线程 相关基础面试题
|
8月前
|
监控 Linux 应用服务中间件
探索Linux中的`ps`命令:进程监控与分析的利器
探索Linux中的`ps`命令:进程监控与分析的利器
167 13
|
7月前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能
|
7月前
|
弹性计算 Linux 区块链
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
220 4
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
|
6月前
|
算法 Linux 调度
探索进程调度:Linux内核中的完全公平调度器
【8月更文挑战第2天】在操作系统的心脏——内核中,进程调度算法扮演着至关重要的角色。本文将深入探讨Linux内核中的完全公平调度器(Completely Fair Scheduler, CFS),一个旨在提供公平时间分配给所有进程的调度器。我们将通过代码示例,理解CFS如何管理运行队列、选择下一个运行进程以及如何对实时负载进行响应。文章将揭示CFS的设计哲学,并展示其如何在现代多任务计算环境中实现高效的资源分配。
|
7月前
|
存储 缓存 安全
【Linux】冯诺依曼体系结构与操作系统及其进程
【Linux】冯诺依曼体系结构与操作系统及其进程
199 1
|
7月前
|
小程序 Linux
【编程小实验】利用Linux fork()与文件I/O:父进程与子进程协同实现高效cp命令(前半文件与后半文件并行复制)
这个小程序是在文件IO的基础上去结合父子进程的一个使用,利用父子进程相互独立的特点实现对数据不同的操作
146 2

热门文章

最新文章