多线程(并发执行)

article/2025/10/7 18:51:04

一、概念区分

1、并行与并发

并行

​ 当系统有一个以上CPU时,同一时刻,当一个CPU在执行一个任务时,另一个CPU在执行另一个任务,两个任务互不抢占CPU资源,可以同时进行(多核CPU,一个CPU执行一个进程)

并发

​ 一个CPU,同一时间,有多个任务在执行。但并发不是真正意义上的“同时进行”,只是将CPU划分成好几个时间片段,每个片段内执行一个任务,然后在这几个片段之间来回切换,由于CPU处理速度快,让用户感觉像是多个任务在同时执行。

区别:

  • 并行是某一时刻,真正有多个程序在运行;并发是在一段时间内,宏观上多个程序同时运行。

  • 并发,指多个事情,在同一时间段内同时发生了;多个任务之间是相互抢占资源的

    并行,指多个事情,在同一时间点上同时发生了;多个任务之间是不相互抢占资源的

  • 只有在多个CPU或CPU多核时,才会发生并行,否则看似同时发生的事情,都是并发的

2、进程与线程

进程

​ 指系统中正在运行的一个应用程序;是资源分配的最小单位

线程

​ 是进程内独立执行的一个单一顺序的控制流;是系统分配处理器时间资源的基本单位;是程序执行的最小单位

在这里插入图片描述

区别

  • 进程之间数据不共享
  • 线程之间可以共享资源

二、线程的生命周期

​ 生命周期:在程序开发中,一个对象从被实例化完成,到这个对象使用结束并销毁的整个过程,类似于人的一生

线程的生命周期:一个线程被实例化,到这个线程销毁的整个过程

线程的状态

  • 新建:New

​ 一个线程被实例化完成,但是还没有做任何动作

  • 就绪:Ready

​ 一个线程已经被启动 (调用start()方法),开始争抢CPU的时间片

  • 运行:Run

​ 一个线程抢到了CPU的时间片,开始执行这个线程中的逻辑

  • 阻塞:Interrupt

​ 一个线程在运行的过程中,受到某些操作的影响,放弃已经获取的CPU时间片,并且不再参与CPU时间片的争抢,此时线程处于挂起状态

  • 死亡:Dead

​ 一个线程对象需要被销毁
在这里插入图片描述

三、开启线程的方式

1、继承Thread类,实现其run()方法

//要自定义一个线程类,并且该类要继承Thread类
class MyThread extends Thread{//重写run方法@Overridepublic void run() {for(int i=0;i<5;i++) {System.out.println("子线程逻辑:"+i);}}
}
public class ThreadClass {public static void main(String[] args) {MyThread mt=new MyThread();  //新建mt.start();    //就绪System.out.println("主线程逻辑执行结束");}
}
/*输出结果:
主线程逻辑执行结束
子线程逻辑:0
子线程逻辑:1
子线程逻辑:2
子线程逻辑:3
子线程逻辑:4
*/

如果是串行运行,则“主线程逻辑执行结束”这句话应该最后执行。但由于并发执行的多线程存在,使得主程序逻辑先执行完毕,在执行子线程

注意:只有调用start方法才会启动线程,并且使该线程执行run方法;如果直接调用run方法,则并没有开启线程,即线程不会进入就绪状态。

2、实现Runnable接口,实现其run()方法

/** Runnable接口是一个函数式接口,可以采用Lambda表达式实现其run方法*/
public class ThreadClass {public static void main(String[] args) {Runnable r1=()->{for(int i=0;i<5;i++) {System.out.println("子线程中的逻辑:"+i);}};Thread t=new Thread(r1);  //新建t.start();    //就绪System.out.println("主线程逻辑执行结束");}
}
//输出结果同上

3、实现Callable接口

与Runnable接口类似,只是该方式有返回值,但Runnable没有返回值

需要使用一个中介FutureTask

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class Test {public static void main(String[] args) {//返回值是int类型Callable callable=()->{int result=0;for(int i=0;i<100;i++) {result+=i;}return result;};//Thread thread=new Thread(callable); 不能直接像创建Runnable接口一样//知道返回值是int性。使用泛型约束FutureTask<Integer> task=new FutureTask<> (callable);Thread thread=new Thread(task);thread.start();//获取计算结果Integer integer = null;try {integer = task.get();  //该方法会抛出两个异常,需要手动处理} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}  System.out.println(integer);}
}

4、异同点

  • 继承Thread类,可读性更高,但是如果某个类类继承了Thread类,那么该类将不能再继承其他类,这有可能会破坏原有的继承结构
  • 使用Runnable接口,程序可对象降低,但不会破坏继承结构,一般多使用这种方式

四、线程的常用方法

1、线程的命名setName

  • 实例化一个线程,使用setName()方法
  • 实例化一个线程的同时,通过构造方法对线程进行命名
  • 3、使用用户自定义的线程类,在实例化的同时,进行名字的赋值
    需要给自定义线程类添加对应的构造方法
class MyThread extends Thread{public MyThread() {}public MyThread(String name) {this.setName(name);     //使用setName()方法//super(name);  //直接调用父类的构造方法}
}
public class ThreadClass {public static void main(String[] args) {//1、实例化一个线程,使用setName()方法Thread t=new Thread();t.setName("用户线程1");System.out.println(t.getName());//2、实例化一个线程的同时,通过构造方法对线程进行命名//  构造方法:Thread(Runnable r,String name);Thread t2=new Thread(()->{},"用户线程2"); System.out.println(t2.getName());//3、使用用户自定义的线程类,在实例化的同时,进行名字的赋值//   需要给自定义线程类添加对应的构造方法MyThread t3=new MyThread("用户线程3");System.out.println(t3.getName());}
}

2、线程休眠sleep(Run->Interrupt)

  1. 调用**sleep()**方法,参数:以毫秒为单位的时间差
  2. 会抛出InterruptedException异常,需要处理
  3. 使得线程由运行状态变为阻塞状态,当休眠时间到达时,才会重新变为就绪状态。即使此时系统中没有其他可执行的线程,处于sleep的线程也依然不会执行
class MyThread extends Thread{//重写run方法@Overridepublic void run() {for(int i=0;i<5;i++) {System.out.println(+i);//线程休眠//参数:以毫秒为单位//需要捕获异常try {Thread.sleep(1000);  //休眠1秒} catch (InterruptedException e) {e.printStackTrace();}   }}
}
public class ThreadClass {public static void main(String[] args) {//调用threadSleep方法threadSleep();}/****线程休眠****/public static void threadSleep() {//实例化一个线程MyThread mt=new MyThread();mt.start();}
}
//输出形式:每隔1秒输出一个i值

3、线程的优先级setPriority

  1. 调用**setPriority()**方法,参数:[0,10]范围内的一个整数,默认是5
  2. 设置优先级,只是设置这个线程可以抢到CPU时间片的概率,并不是优先级高的线程一定能抢到CPU时间片(不是优先级高的线程一定先执行,也不是优先级高的线程执行完再执行其他线程)
  3. 设置优先级必须要放在线程开始(start)之前
public class ThreadClass {public static void main(String[] args) {threadPriority();}/****设置线程的优先级***/public static void threadPriority() {Runnable r=()->{for(int i=0;i<5;i++){System.out.println(Thread.currentThread().getName()+":"+i);}};//1、线程实例化Thread t1=new Thread(r,"Thread-1");Thread t2=new Thread(r,"Thread-2");//2、设置优先级, 必须要将该操作放在线程开始(start)之前t1.setPriority(10);t2.setPriority(1);//3、线程启动t1.start();t2.start();}
}
//输出结果:交替执行

4、线程的礼让yield(Run->Ready)

  1. 调用**yield()**方法,类方法
  2. 线程礼让是指让当前运行的线程释放自己的CPU资源,由运行状态,回到就绪状态。**但并不意味着一定去执行另一个线程,**此时依然是两个线程进行CPU时间片的抢夺
public class ThreadClass {public static void main(String[] args) {threadYield();}/***线程的礼让***/public static void threadYield() {Runnable r=()->{for(int i=0;i<10;i++) {System.out.println(Thread.currentThread().getName()+":"+i);//线程礼让if(i==3) {Thread.yield();}}};Thread t1=new Thread(r,"Thread-1");Thread t2=new Thread(r,"Thread-2");t1.start();t2.start();}
}
/*输出结果:
Thread-2:0
Thread-2:1
Thread-2:2
Thread-2:3   //Thread-2礼让,CPU被Thread-1抢到
Thread-1:0
Thread-1:1
Thread-1:2
Thread-1:3  //Thread-1礼让,但是CPU还是被Thread-1抢到,Thread-1继续执行
Thread-1:4
Thread-1:5
Thread-1:6
Thread-1:7
Thread-1:8
Thread-1:9   //Thread-1执行完毕,Thread-2接着执行
Thread-2:4
Thread-2:5
Thread-2:6
Thread-2:7
Thread-2:8
Thread-2:9
*/

5、线程合并join

  1. 执行join的线程,在该过程中,其他线程阻塞,待此线程执行完毕,再执行其他线程。(插队)
  2. 抛出InterruptException异常
public class JoinTest {public static void main(String[] args) {Runnable runnable=()->{for(int i=0;i<100;i++) {System.out.println("vip线程"+i);}};Thread thread=new Thread(runnable);thread.start();//主线程输出100次for(int i=0;i<100;i++) {/** 当主线程运行到第50次时,调用join方法,那么此时会等join方法加入的线程执行完毕,在执行主线程* */if(i==50) {try {thread.join();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("main"+i);}}
}
/*输出:在50之前,主线程和子线程交替执行,但是等到主线程为50时,此时子线程会执行直到100结束,然后主线程才执行
*/

6、守护线程setDaemon

  1. 如果所有的用户线程结束,那么守护线程会自动死亡;虚拟机不需要等待守护线程执行结束
  2. setDaemon默认是false,如果要设置一个线程为守护线程,则改为true即可
public class DaemonTest {public static void main(String[] args) {Runnable r1=()->{while(true) {System.out.println("守护线程");}};for(int i=0;i<10;i++) {System.out.println("主线程"+i);}Thread thread=new Thread(r1);thread.setDaemon(true);  //默认是false,表示用户线程thread.start();}
}
//守护线程是一个死循环,但是等待主线程执行结束后,该线程会自动停止

五、线程安全问题

临界资源:多个线程共享的资源。当多个线程同时去访问这个共享资源时,会出现线程安全问题

1、产生的原因

当一个线程在访问并操作某个资源的过程中,还没来得及完全修改该资源,CPU时间片就被其他线程抢走

//用四个线程模拟四个售票员卖票,仓库中的余票即为临界资源
class TicketCenter{//描述剩余票的数量public static int restCount=100;
}
public class SourseProblem {public static void main(String[] args) {Runnable r=()->{//当余票大于0时,可以继续售票while(TicketCenter.restCount>0) {System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ --TicketCenter.restCount+"张");}};//四个线程模拟四个售票员,线程名模拟售票员名Thread t1=new Thread(r,"Thread-1");Thread t2=new Thread(r,"Thread-2");Thread t3=new Thread(r,"Thread-3");Thread t4=new Thread(r,"Thread-4");t1.start();t2.start();t3.start();t4.start();}
}

输出结果:

在这里插入图片描述

出现临界资源问题,这是因为一个线程在计算余票的过程中,还没来的及将计算、或计算后的结果还没来得及赋给restCount,CPU就被其他线程抢走,此时其他线程中的余票是当前抢到时刻的余票值。

2、解决方法

  • JVM实现的synchronized
  • JDK实现的ReentrantLock

方式一:使用同步代码块

用synchronized修饰多线程需要访问的代码

class TicketCenter{//描述剩余票的数量public static int restCount=100;
}
public class SourseProblem {public static void main(String[] args) {Runnable r=()->{//当余票大于0时,可以继续售票while(TicketCenter.restCount>0) {//同步监视器synchronized("") {if(TicketCenter.restCount<=0) {return;}System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ --TicketCenter.restCount+"张");}}};//四个线程模拟四个售票员,线程名模拟售票员名Thread t1=new Thread(r,"Thread-1");Thread t2=new Thread(r,"Thread-2");Thread t3=new Thread(r,"Thread-3");Thread t4=new Thread(r,"Thread-4");t1.start();t2.start();t3.start();t4.start();}
}

方法二:同步方法:使用关键字synchronized修饰的方法

将上面的同步代码段用一个方法实现

  1. 静态方法:同步监视器就是:当前类.class
  2. 非静态方法:同步监视器是 this
class TicketCenter{//描述剩余票的数量public static int restCount=100;
}
public class SourseProblem {public static void main(String[] args) {Runnable r=()->{while(TicketCenter.restCount>0) {soldTicket();}};Thread t1=new Thread(r,"Thread-1");Thread t2=new Thread(r,"Thread-2");Thread t3=new Thread(r,"Thread-3");Thread t4=new Thread(r,"Thread-4");t1.start();t2.start();t3.start();t4.start();}//同步方法public synchronized static void soldTicket(){if(TicketCenter.restCount<=0) {return;}System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ --TicketCenter.restCount+"张");}
}

方式三:同步锁

显式定义同步锁对象来实现同步

class TicketCenter{//描述剩余票的数量public static int restCount=100;
}
public class SourseProblem {public static void main(String[] args) {//实例化一个锁对象ReentrantLock rt=new ReentrantLock();Runnable r=()->{while(TicketCenter.restCount>0) {//对临界资源上锁rt.lock();if(TicketCenter.restCount<=0) {return;}System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ --TicketCenter.restCount+"张");//对临界资源解锁rt.unlock();}};Thread t1=new Thread(r,"Thread-1");Thread t2=new Thread(r,"Thread-2");Thread t3=new Thread(r,"Thread-3");Thread t4=new Thread(r,"Thread-4");t1.start();t2.start();t3.start();t4.start();}
}

3、死锁

多个线程彼此持有对方所需要的锁,而不释放自己的锁

//线程A、B互相等待对方释放拥有的锁
public class DeadLock {public static void main(String[] args) {Runnable runnable1=()->{synchronized("A"){System.out.println("A线程持有了A锁,等待B锁");//此时A线程已经持有A锁了,让它继续持有B锁/*为了确保产生死锁try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}*/synchronized("B"){System.out.println("A线程持有了A锁和B锁");}}};Runnable runnable2=()->{synchronized("B"){System.out.println("B线程持有了B锁,等待A锁");//此时B线程已经持有B锁了,让它继续去持有A锁synchronized("A"){System.out.println("B线程持有了A锁和B锁");}}};Thread t1=new Thread(runnable1);Thread t2=new Thread(runnable2);t1.start();t2.start();}
}
/*输出结果:
B线程持有了B锁,等待A锁
A线程持有了A锁,等待B锁
(程序未结束)
*/

上述代码其实不能完全产生死锁,如果在A线程获取B锁之前,B线程都没有获得执行机会,那么B线程就不会获取到B锁,此时程序依然会执行,不会产生死锁。为了一定产生死锁情况,可以在A线程执行过程中调用一个sleep方法。

4、线程通信:解决死锁的办法

方式1:synchronized下的通信

  • wait():等待,当前的线程释放对同步监视器的锁定,并且让出CPU资源,使得当前的线程进入等待队列中
  • notify():通知,唤醒在此同步监视器上等待的一个线程(具体哪一个由CPU决定),使这个线程进入锁池
  • notifyAll():通知,唤醒在此同步监视器上等待的所有线程,使这些线程进入锁池
public class DeadLock {public static void main(String[] args) {Runnable runnable1=()->{synchronized("A"){System.out.println("A线程持有了A锁,等待B锁");//A线程释放A锁(捕获异常)try {"A".wait();} catch (InterruptedException e) {e.printStackTrace();}synchronized("B"){System.out.println("A线程持有了A锁和B锁");}}};Runnable runnable2=()->{synchronized("B"){System.out.println("B线程持有了B锁,等待A锁");synchronized("A"){System.out.println("B线程持有了A锁和B锁");//此时B线程已经执行完成了,但是A线程任然还在等待,因此需要唤醒A线程"A".notify();}}};Thread t1=new Thread(runnable1);Thread t2=new Thread(runnable2);t1.start();t2.start();}
}
/*输出结果:
A线程持有了A锁,等待B锁
B线程持有了B锁,等待A锁
B线程持有了A锁和B锁
A线程持有了A锁和B锁
*/

方式2:Lock锁下的通信,采用Condition控制通信。JUC中的类(java.util.comcurrent类)

  • await():等价于wait()
  • signal():等价于notify()
  • signalAll():等价于notifyAll()

4、多线程下的单例类

懒汉式单例类会出现问题

//定义一个单例类
class Boss{//构造器私有化private Boss() {System.out.println("一个Boss对象被实例化了");}private static Boss instance=null;//外部类只能通过该方法获取Boss类的实例public static Boss getBoss() {if(instance==null) {instance=new Boss();}return instance;}
}
public class SingletonTest {public static void main(String[] args) {Runnable runnable=()->{Boss.getBoss();};//开辟了100条线程去获取这Boss实例for(int i=0;i<100;i++) {new Thread(runnable).start();}}
}

当多线程去执行这个单例类时,还是希望只产生一个实例对象,但程序输出结果明显不是,这是由于多线程导致的。

修改方式1:对临界资源上锁,使用同步代码

//定义一个单例类
class Boss{//构造器私有化private Boss() {System.out.println("一个Boss对象被实例化了");}private static Boss instance=null;public static Boss getBoss() {//同步代码段synchronized("") {if(instance==null) {instance=new Boss();}}return instance;}}public class SingletonTest {public static void main(String[] args) {Runnable runnable=()->{Boss.getBoss();};//开辟了100条线程去获取这Boss实例for(int i=0;i<100;i++) {new Thread(runnable).start();}}
}

修改方式2:对临界资源上锁,使用同步方法

class Boss{//构造器私有化private Boss() {System.out.println("一个Boss对象被实例化了");}private static Boss instance=null;//同步方法public static synchronized Boss getBoss() {if(instance==null) {instance=new Boss();}return instance;}
}public class SingletonTest {public static void main(String[] args) {Runnable runnable=()->{Boss.getBoss();};//开辟了100条线程去获取这Boss实例for(int i=0;i<100;i++) {new Thread(runnable).start();}}
}

六、线程池

线程池在系统启动时就创建大量空闲的线程。提前创建多个线程,放入线程池,使用时直接从线程池中获取,使用完放回池中

1、作用

可以避免频繁创建销毁线程的过程,实现充分利用

  • corePoolSize:核心池的大小(可以放多少个线程)
  • maximumPoolSize:最大线程数(一次可以同时运行的线程数量)
  • keepAliveTime:线程没有任务时最多保持多长时间后会终止

2、创建方式

  • ExecutorService接口:线程池真正的接口
  • Executor:创建线程的工具类,调用该类的newFixedThreadPool(corePoolSizesize)方法来创建线程池
  • execute:执行Runnable接口的,无返回值
  • Future submit:执行Callable接口的,有返回值
  • shutdown:关闭连接
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolTest {public static void main(String[] args) {Runnable r=()->{System.out.println(Thread.currentThread().getName());};//创建线程池,设置大小为10ExecutorService service=Executors.newFixedThreadPool(10);//执行service.execute(r);service.execute(r);service.execute(r);service.execute(r);//关闭连接service.shutdown();}
}
/*输出结果:
pool-1-thread-3
pool-1-thread-4
pool-1-thread-2
pool-1-thread-1
*/

七、JUC组件

1、未来任务FutureTask

利用Callable创建线程时,有返回值,该值由Future进行封装,FutureTask实现了RunnableFuture接口,而该接口继承自Runnable和Future接口,因此FutureTask既可以当做一个任务执行,也可以有返回值。

当计算一个任务需要很长时间时,可使用FutureTask来封装这个任务,使得主线程在完成自己的任务后在去获取这个计算结果

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class FutureTaskTest {public static void main(String[] args) {//创建一个Clallable接口,有返回值,给子线程执行Callable<Integer> cla=()->{int result=0;for(int i=0;i<100;i++) {Thread.sleep(10);  //每一次计算时都让让主线程执行一段时间result+=i;}return result;};//新建一个FutureTask实例FutureTask<Integer> futureTask=new FutureTask<>(cla);//执行计算任务的线程Thread t1=new Thread(futureTask);t1.start();//创建Runnable接口,给主线程执行Runnable runnable=()->{System.out.println("主线程任务正在执行");try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}};Thread t2=new Thread(runnable);t2.start();//得到有返回值的输出try {System.out.println(futureTask.get());} catch (InterruptedException | ExecutionException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}
/*输出结果:
另一个线程任务正在执行
4950
*/
//如果将Callable执行体中的Thread.sleep(10);去掉,则执行结果为:4950  另一个线程任务正在执行。

2、阻塞队列BlockingQueue

利用BlockingQueue作为线程同步的工具,主要用来实现消费者生产者设计模式。详见《生产者消费者设计模式》

3、叉链接ForkJoin

主要用于并行计算中,将大的任务分成小的任务进行计算,再把小任务的结果合并成总的计算结果


http://chatgpt.dhexx.cn/article/DafpOK5J.shtml

相关文章

2.多线程并发

1.说说你知道的创建线程的方式 1、继承Thread类&#xff0c;重写run方法。2、实现Runnable接口&#xff0c;重写run方法。3、实现Callable接口&#xff0c;重写call方法。4、通过线程池创建线程。 https://blog.csdn.net/u013541140/article/details/95225769 CachedThreadPoo…

C++多线程并发(一)--- 线程创建与管理

文章目录 前言一、何为并发1.1 并发与并行1.2 硬件并发与任务切换1.3 多线程并发与多进程并发 二、如何使用并发2.1 为什么使用并发2.2 在C中使用并发和多线程 三、C线程创建3.1 C11新标准多线程支持库3.2 线程创建的简单示例 更多文章&#xff1a; 前言 我们都听说过摩尔定律…

lrzsz

lrzsz是一款程序&#xff0c;在linux中可以代替ftp的上传和下载 安装lrzsz yum install -y lrzsz上传&#xff1a;rz 将文件上传到本地&#xff0c;默认上传到当前目录 该程序支持拖拽上传&#xff0c;如下图所示 上传成功后查看本地 下载&#xff1a;sz filename 例如&am…

linux之lrzsz

1、lrzsz介绍 我们利用lrzsz进行windows和linux间的文件上传下载 2、安装 在ubuntu系统下 sudo apt-get install lrzsz 在centos系统下 yum install lrzsz 3、使用 1)、windows上传文件到linux环境,使用如下命令 rz

文件传输工具rzsz

mac安装rz sz? 之前在item2上使用使用rz和sz时就直接夯住 发现是需要配置下 mac使用rz&#xff0c;sz进行文件传输(默认使用的终端为iterm2) 一、安装lrzsz brew install lrzsz 二、下载iterm2-zmodem 执行 git clone https://github.com/aikuyun/iterm2-zmodem.git cd …

【lrzsz】Linux上lrzsz的安装和使用

一、lrzsz简介 rz&#xff0c;sz是Linux/Unix同Windows进行ZModem文件传输的命令行工具。 rz 可以很方便的从客户端传文件到服务器&#xff0c;sz也可以很方便的从服务器传文件到客户端&#xff0c;就算中间隔着跳板机也不影响。 rz(receive Zmodem) sz(send Zmodem) 远程文…

Linux lrzsz 详解

和 FileZilla 功能类似用于上传文件&#xff0c;上传速度比较慢适用于比较小的文件 安装指令 $ sudo yum install lrzsz 使用方式 $ rz 注&#xff1a;1> rz 指令在那个目录就在在那个目录上传文件 2> 文件要上的目录一定要有权限&#xff0c;否则上传失败

linux rz命令安装

新搞的云服务器用SecureCRT不支持上传和下载&#xff0c;没有找到rz命令。记录一下如何安装rz/sz命令的方法。 一、工具说明 在SecureCRT这样的ssh登录软件里, 通过在Linux界面里输入rz/sz命令来上传/下载文件. 对于某些linux版本, rz/sz默认没有安装所以需要手工安装。 sz: 将…

rz sz

linux上很方便的上传下载文件工具rz和sz (本文适合linux入门的朋友) ######################################################### #《老男孩linux就业培训中心-初级班第七期第一节内容总结。 #linux上很方便的上传下载文件工具rz和sz #date:2011-06-15 #作者&#xff1a;老男…

Linux的rz命令

linux服务器rz命令上传文件 2016年09月10日 19:56:02 阅读数&#xff1a;11712 1、首先&#xff0c;要是服务器不支持rz命令的话&#xff0c;需要安装执行 yum -y install lrzsz 2、再输入rz -be命令&#xff0c;选择需要上传的本地文件

llrzsz

文章目录 官网解压配置编译安装复制到开发板并执行使用lrz从PC传开发板使用lsz从开发板传PC参考链接 今天给大家推荐一个很好用的工具。 你是不是感觉在没有网络时往linux中下载程序很麻烦&#xff08;SD卡插拔&#xff09;&#xff0c;今天就教大家怎么通过串口和linux文件系统…

linux系统下的rz、sz详解

对于linux服务器来说&#xff0c;通常我们是通过一些ssh工具进行远程访问连接的&#xff0c;而对于经常使用它的人来说&#xff0c;少不了将文件上传下载到服务器。如何能够快速的同服务器进行文件的交互尤为重要。不然每次都打开单独的ssh客户端或者ftp很是浪费时间。今天&…

linux rzsz(lrzsz)安装

lrzsz 官网入口&#xff1a;https://ohse.de/uwe/software/lrzsz.html lrzsz是一个unix通信套件提供的X&#xff0c;Y&#xff0c;和ZModem文件传输协议,可以用在windows与linux 系统之间的文件传输&#xff0c;体积小速度快。感觉可以替代ftp了 lrzsz 在线安装&#xff1a; …

【Linux】第三章Linux环境基础开发工具使用(yum+rzsz+vim+g++和gcc+gdb+make和Makefile+进度条+git)

&#x1f3c6;个人主页&#xff1a;企鹅不叫的博客 ​ &#x1f308;专栏 C语言初阶和进阶C项目Leetcode刷题初阶数据结构与算法C初阶和进阶《深入理解计算机操作系统》《高质量C/C编程》Linux ⭐️ 博主码云gitee链接&#xff1a;代码仓库地址 ⚡若有帮助可以【关注点赞收藏】…

【Linux基础】Linux软件包管理器yum的使用指南rzsz安装

【Linux基础】Linux软件包管理器yum的使用指南|rzsz安装 前言 主页&#xff1a; 潮.eth的博客_CSDN博客-C学习,C学习,数据结构and算法领域博主 Linux基础专栏&#xff1a; Linux基础_潮.eth的博客-CSDN博客 正文 文章目录 【Linux基础】Linux软件包管理器yum的使用指南|rzsz安装…

linux虚拟机rzsz安装(wget方法,自测可用)

1、mkdir /usr/local/lszrz创建文件夹后进入这个文件夹&#xff0c;使用wget https://ohse.de/uwe/releases/lrzsz-0.12.20.tar.gz --no-check-certificate下载安装包lrzsz-0.12.20.tar.gz。这里的--no-check-certificate是不进行证书验证的意思&#xff0c;我没有加这个会产生…

linux 下安装安装rzsz命令

我们在linux上部署代码的时候经常需要上传文件到linux&#xff0c;有时候也需要从linux上下载文件到本地&#xff0c;大部分人都直接借助于ftp工具&#xff0c; 然而其实我们可以直接通过rz和sz上传下载文件&#xff0c;但是rz和sz命令不是linux默认自带的命令&#xff0c;需要…

Linxux应用开发-串口下载命令rzsz交叉编译

1.1 简介 rz/sz工具是通过Zmodem协议传输文件的命令&#xff0c;常用于Linux与windows之前的数据传输。 这篇文章就介绍如何在交叉编译rz/sz命令&#xff0c;并在Linux开发板上完成测试。 1.1.1 什么是rz/sz (lsz/lrz) rz/sz 通过Zmodem协议传输数据的命令&#xff0c;通过串…

kafka消息队列使用场景

一、消息队列概述 消息队列中间件是分布式系统中重要的组件&#xff0c;主要解决应用解耦&#xff0c;异步消息&#xff0c;流量削锋等问题&#xff0c;实现高性能&#xff0c;高可用&#xff0c;可伸缩和最终一致性架构。目前使用较多的消息队列有ActiveMQ&#xff0c;RabbitM…

Springboot之Kafka

Kafka介绍 Kafka属于分布式日志系统。 主要应用场景是&#xff1a;日志收集系统和消息系统。 Kafka主要设计目标如下&#xff1a; 以时间复杂度为O(1)的方式提供消息持久化能力&#xff0c;即使对TB级以上数据也能保证常数时间的访问性能。高吞吐率&#xff0c;即使在非常廉价…