01.04

编程入门 行业动态 更新时间:2024-10-14 12:23:29

01.04

01.04

一、线程相关的名称解释(了解)

1、什么是多线程

之前自己写的代码,都是单线程的,程序自上而下顺序执行,只有一条执行路径。
现在我们希望我们自己写的程序,能够同时做好几件事情,例如:一边聊天,并且支持多个好友聊天,一边传文件。
这个时候就需要开启多线程。
即多线程就是指一个应用程序有多条执行路径同时运行。

2、单线程和多线程的区别

(1)单线程:如果其中一句代码阻塞了,剩下的代码无法运行,我们CPU等资源对于这个线程来说就停止了。
相当于单行线,堵车
(2)多线程:如果其中一个线程阻塞了,只是这个线程阻塞,其他线程正常运行。

3、并行与并发

并行(parallel):指两个或多个事件在同一时刻发生(同时发生)。
要求:有多个处理器(CPU)
比喻:路线是多行线,过收费站,有多个收费口。
并发(concurrency):指两个或多个事件在同一个时间段内发生。指在同一个时刻只能有一条指令执行,但多个进程的指令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果。
不要求:有多个处理器
比喻:路线是多行线,过收费站,只有一个收费口。
但是这个收费口动作非常快。
如果线程个数增多,等待的情况会越来越明显。

现在的程序,基本上是并行与并发同时存在。

4、进程与线程

程序(Programm):选择任意一种编程语言(C,C++,Java,Python等),为了完成一个任务,功能,而编写了一段代码。
这段代码最终会被编译为一组指令。那么一个程序就是一组指令的集合。
如果程序没有运行,相当于存储在硬盘上的一个普通的文件。
软件(Software):一个软件中可能有一个或多个的程序。
软件 = 一个或多个的程序 + 资源文件(图片,音频素材等)

            码农、程序员(关注是写代码),软件工程师(初级、中级、高级)。

进程(Process):是程序的一次运行。即一个程序如果运行了多次,就会有多个进程。
操作系统分配内存等资源是以进程为单位的。不同的进程之间是不能共享内存资源的。哪怕是同一个应用程序的两次运行,
也是独立的两个进程,也无法共享内存资源。
进程之间的数据共享的成本很高,需要通过:文件、网络通信才能实现数据的共享。
而且进程之间的切换,也是成本很高。因为目前的操作系统成为多任务,那么CPU同一个时刻只能处理一个任务,
但是我们电脑会同时启动很多个进程,就算现在多核处理器,仍然数量不可能一个处理器负责一个进程,
所以需要轮循或抢夺。每一次轮换,操作系统需要记录当前这个进程运行到哪个指令,目前的各个资源的状态是什么样的。
线程(Thread):线程是一个进程中的其中一条执行路径。
一个进程至少有一个线程。如果只有一个线程,称为单线程程序。
如果一个进程中有多个线程,称为多线程程序。
同一个进程中的多个线程是可以共享内存的,例如:堆内存、方法区内存。
那么,在同一个进程中的多个线程之间需要数据共享的话,就比较简单。

               另一点,同一个进程中的多个线程如果需要轮循或抢夺,那么成本相对比较低,我们只要记录当前线程的执行到哪一句指令即可,JVM中有一块内存区域:程序计数器,它就负责记录每一个线程目前执行到哪一个指令了,下一条指令是什么。并且每一个线程又有独立的内存,例如:栈内存有的时候会把线程称为轻量级的进程。进程是操作系统分配资源和调度的最小单位。线程是CPU调度的最小单位。多线程和多进程的目标:可以同时做好几件事情,然后可以充分利用CPU资源。

JVM内存:
(1)方法区:加载的类信息,静态变量,常量等
(2)堆:存储new的对象
(3)栈:局部变量
A:虚拟机栈:Java方法
B:本地方法栈 :native方法
(4)程序计数器:记录每一个线程的下一条指令

实现java.lang.Runnable接口

步骤:
(1)自定义一个线程类,实现Runnable接口
(2)必须重写父接口的一个方法:run方法
public void run(){
线程体:这个线程要完成的任务代码
}
(3)创建自定义线程类的对象
(4)启动线程:
A:创建Thread类的对象,并把自定义线程类的对象传给Thread类的对象
B:调用Thread类的对象的start()
当线程启动之后,相当于将线程交给了线程调度器来管理。

main是一个线程
my是另一个线程对象
public class Runnable {public static void main(String[] args) {MyRunnable my = new MyRunnable();
//        my.start();//无法直接调用start(),因为父类Object中没有,父接口Runnable没有。//刚才我们说java.lang.Thread类有,我们借用Thread类的start方法帮我们启动线程//所以我们需要创建Thread类的对象,并且在创建Thread类的对象的时候,告诉它执行谁的run()Thread t = new Thread(my);//使用了Thread(Runnable target) 构造器t.start();}
}
class MyRunnable implements Runnable{@Overridepublic void run() {//例如:打印1-10之间的偶数for (int i=2; i<=100; i+=2){System.out.println("i = " + i);}}
}

多线程不是Java的概念。
属于计算机操作系统原理中的概念。
Java支持多线程开发。

多线程的课程分两个阶段:JavaSE(一天)、Java高级(juc)

二、Java中如何支持多线程开发

1、JavaSE中有两种方式:

(1)继承Thread类
(2)实现Runnable接口

2、继承java.lang.Thread类

步骤:
(1)自定义一个线程类,继承Thread类
(2)必须重写父类的一个方法:run方法
public void run(){
线程体:这个线程要完成的任务代码
}
(3)创建自定义线程类的对象
(4)启动线程:调用线程对象的start()
当线程启动之后,相当于将线程交给了线程调度器来管理。

main是一个线程,
my是一个线程
public class Thread {public static void main(String[] args) {MyThread my = new MyThread();
//        my.run();//相当于调用普通的方法,不是多线程运行机制,只能顺序执行,// 即下面的代码必须等run()结束之后才能运行,不是同时运行my.start();//启动my线程之后,my线程的run()方法中的代码将与接下来main方法中代码,“同时”运行//start()是从Thread类继承的//打印1-10的奇数for (int i=1; i<=100; i+=2){System.out.println("main: i = " + i);try {if(i==5){Thread.sleep(1000);}} catch (InterruptedException e) {e.printStackTrace();}}}
}class MyThread extends Thread{@Overridepublic void run() {//例如:打印1-10之间的偶数for (int i=2; i<=100; i+=2){System.out.println("i = " + i);}}
}

三、Thread类的API方法

1、构造器

Thread()
Thread(Runnable target)
Thread(String name)
Thread(Runnable target, String name)

2、Thread常用方法

(1)getName():获取线程名称
默认情况下,线程的名称是:Thread-编号
例如:Thread-0
例如:Thread-1
(2)获取当前线程对象的静态方法
public static Thread currentThread()
(3)getPriority():获取线程的优先级
setPriority():设置线程的优先级
优先级高低会影响线程抢夺CPU的概率,如果优先级高的,抢到CPU的概率会提高。
优先级一共有10个等级:为1-10,不能超过这个范围。
如果优先级不在 MIN_PRIORITY 到 MAX_PRIORITY 范围内,就会报IllegalArgumentException。
MIN_PRIORITY:1
MAX_PRIORITY:10
NORM_PRIORITY:5

public class TestThreadMethod1 {public void test01(){Thread t = new Thread();System.out.println(t.getName());//Thread-0}//    @Test
//    public void test02(){//如果使用JUnit测试线程,要注意:JUnit的@Test的方法也是一个线程,如果它结束了,其他线程也会结束,因为JVM退出了public static void main(String[] args) {System.out.println("hello main");//这句代码一定先执行,剩下的线程还未start//如果使用main方法测试线程,当其他线程没有结束,此时就算main方法代码已经完成了,也不会退出JVMnew Thread(){public void run(){for (int i=1; i<=5; i++){//getName()从Thread父类继承的System.out.println(getName()+":i="+i);}}}.start();//new 父类(实参列表){...}//说明匿名内部类中调用了父类的有参构造,super(name)new Thread("自定义线程2"){public void run(){for (int i=1; i<=5; i++){//getName()从Thread父类继承的System.out.println(getName()+":i="+i);}}}.start();System.out.println("-----------------------------");//main线程负责打印---new Thread(new Runnable(){public void run(){for (int i=1; i<=5; i++){//Thread.currentThread(),获取当前线程对象,即当前哪个线程再执行这句代码,得到的就是哪个线程对象,它也是Thread类型的System.out.println(Thread.currentThread().getName()+":i="+i);}}}).start();new Thread(new Runnable(){public void run(){for (int i=1; i<=5; i++){System.out.println(Thread.currentThread().getName()+":i="+i);}}},"自定义线程4").start();}
}
public class ThreadMethod2 {public static void main(String[] args) {MyThread t1 = new MyThread();t1.start();MyThread t2 = new MyThread();t2.setPriority(10);t2.start();MyThread t3 = new MyThread();// t3.setPriority(100);//IllegalArgumentExceptiont3.start();//如何获取main线程的名称和优先级呢?System.out.println("主线程的名称:" + Thread.currentThread().getName());System.out.println("主线程的优先级:" + Thread.currentThread().getPriority());}
}
class MyThread extends Thread{public void run(){System.out.println(getName() + "的优先级:" + getPriority());}
}

3、Thread类的API方法

(4)线程的休眠:
public static void sleep(long millis) throws InterruptedException
public static void sleep(long millis, int nanos)throws InterruptedException
InterruptedException:编译时异常

(5)线程的暂停:
public static void yield():让出当前线程的CPU资源,当前线程会与其他等待CPU资源的线程再次竞争
如果其他线程的优先级比较高,那么当前线程yield暂停之后,CPU资源被其他线程抢走的概率很高。

(6)线程的加塞:
public final void join()throws InterruptedException
无限制加塞,直到加塞的线程结束,被加塞的线程才有机会。
public final void join(long millis)throws InterruptedException
public final void join(long millis, int nanos)throws InterruptedException
限时加塞,在指定时间范围内,被加塞线程没有机会抢夺CPU资源。

public class ThreadMethod3 {public static void main(String[] args) {new Thread(){public void run(){for(int j=1; j<=100; j++){System.out.println("j = " + j);}}}.start();//倒计时的效果//下面的代码由main线程负责for (int i=10; i>=1; i--){System.out.println(i);/*try {//try...catch围绕:选中代码,按Ctrl +Alt + T,选中try..catchThread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}*/if(i==10) {Thread.yield();}}}
}
public class ThreadMethod4 {public static void main(String[] args) {TimeCount t = new TimeCount();t.start();for (int i=1; i<=10; i++){System.out.println("main,i=" + i);try {if(i==2){//main线程被t线程加塞//无限制加塞,main线程要等t线程结束,才能继续
//                    t.join();//限时加塞,t线程会加塞 500毫秒,0.5秒t.join(500);}} catch (InterruptedException e) {e.printStackTrace();}}}
}
class TimeCount extends  Thread{public void run(){for (int i=2; i>=1; i--){System.out.println("i = " + i);try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

更多推荐

01.04

本文发布于:2024-03-05 00:26:15,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1710819.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!