Java创建线程(Lambda表达式创建线程)

article/2025/11/8 2:11:35

一、创建线程三种方式

1.1 继承Thread类创建线程类(main线程与t线程交替执行)

1.2 通过Runnable接口创建线程类

弊端是:不能直接使用Thread中的方法需要先获取到线程对象后,才能得到Thread的方法,代码复杂

上述代码中Thread.currentThread()方法返回当前正在执行的线程对象GetName()方法返回调用该方法的线程的名字。

public class RunnableThreadTest implements Runnable {private int i;public void run() {for (i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " " + i);}}public static void main(String[] args) {for (int i = 0; i < 3; i++) {System.out.println(Thread.currentThread().getName() + " " + i);if (i == 2) {RunnableThreadTest rtt = new RunnableThreadTest();new Thread(rtt, "新线程1").start();new Thread(rtt, "新线程2").start();}}}
}

使用Lambda表达式

public class RunnableThreadTest {// 目的是为了代码的重用【静态方法】public static void threadRunCode_Static() {System.out.println(Thread.currentThread().getName() + " " + }// 目的是为了代码的重用【非静态方法】public void threadRunCode() {System.out.println(Thread.currentThread().getName() + " " + i);}@Testpublic void testNoStatic() {// 重用非静态方法中的代码【使用方法引用】RunnableThreadTest temp = new RunnableThreadTest();new Thread(temp::threadRunCode, "线程1").start();}@Testpublic void testStatic() {// 重用静态方法中的代码【使用方法引用】new Thread(RunnableThreadTest::threadRunCode_Static, "线程1").start();}@Testpublic void testLambda() {// 重用静态方法中的代码【使用方法引用】new Thread(() -> {                       System.out.println(Thread.currentThread().getName() + " " + b);},"线程1").start();
}

匿名内部类实现线程

1、继承Thread类

  new Thread() {                                 //1.继承Thread类public void run(){                      //2.重写run方法for(int i = 0;i < 1000;i++) {System.out.println("aaaaaa");}}}.start();                                  //3.开启线程

2、实现Runnable接口

  new Thread(new Runnable() {                 //1.将Runnable子类对象传递给Thread构造方法public void run(){                      //2.重写run方法for(int i = 0;i < 1000;i++) {               System.out.println("bb");}}           }).start();                                 //3.开启线程

1.3   线程的第三种创建方式

  • 使用Callable接口_java.util.concurrent

    image

    • Callable接口与Runnable接口的区别:
      • Runnable没有返回值一说,而且run()方法并不抛出异常
      • Callable中的call方法具有返回值
      • Callable之所以有返回值,也是因为实现了泛型,而Runnable接口不存在泛型

7.1 FutureTask类的学习——java.util.concurrent.FutureTask<V>

image

  • FutureTask的构造器

image

  • 此时可理解为:FutureTask的作用就是接收一个实现了Callable接口的实现类对象

  • 此时注意到FutureTask实现了Runnable接口

    • 也就是说可以把FutureTask的实现类对象传入到Runnable类型
  • 而Thread类中的构造器的参数为Runnable类型
  • 因此梳理后可知

    ①先实现Callable接口

      class myThread_3 implements Callable<String>{@Overridepublic String call() throws Exception {return "线程创建成功";}}
    

    ②将Callable实现类对象传给FutureTask构造器

      FutureTask<String> ft = new FutureTask<>(new myThread_3());* 因为FutureTask实现了Runnable接口,因此以下代码也正确Runnable runner = new FutureTask<String>(new myThread_3());* 接口引用指向实现类对象* 但是此时runner只能访问Runnable中方法,不可以访问FutureTask中的方法
    

    ③创建线程并启动

      new Thread(ft).start();
    

    ④使用FutureTask类中方法

      public V get() throws InterruptedException,ExecutionException通过Thread启动线程之后 可以通过FutureTask存在get方法可以取得call()方法中的返回值/*用到Callable有什么用?只是为了返回一个值?执行线程的代码run用什么代替?*//*回答:此时线程启动start()方法调用的是call()方法,将需要执行的代码放到call()方法中,同时call()方法的特点在于有返回值*/
    
  • 程序

      public class TestCallable{public static void main(String[] args) {FutureTask<String> ft = new FutureTask<String>(new myThread_3());new Thread(ft).start();  //此时的启动需要调用的是call()方法      String result = null;try {result = ft.get();} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}       System.out.println(result);     }   }class myThread_3 implements Callable<String>{@Override   public String call() throws Exception {     System.out.println("此时start()方法调用的是call()方法");return "线程创建成功";}}/*  在JDK1.8中输出结果为:*  ----------------------------*  此时start()方法调用的是call()方法线程创建成功----------------------------* */
    

2. 多线程(获取名字和设置名字)(掌握)

Thread.currentThread()方法返回当前正在执行的线程对象

  • Thread类中的方法使用

    • getName()
    • setName()
    • currentthread()
    • sleep
    • join
    • wait
    • yield
    • setDaemon
  • 获取名字【通过getName()方法获取线程对象的名字】

    •   public final String getName();
      
  • 设置名字

    • 通过构造函数可以传入String类型的名字

        public Thread(String name)public Thread(Runnable target,String name)  
      
    • 通过setName(String)方法可以设置线程对象的名字

        public final void setName(String name);
      
  • 程序实现

      new Thread("线程一") {             //设置线程名字public void run() {设置代码块for(int i = 0;i < 100;i++) {System.out.println(this.getName() + "....aaaa");   //获取线程名字}}}.start();new Thread() {public void run() {this.setName("线程3");       //设置线程名字for(int i = 0;i < 100;i++) {System.out.println(this.getName() + "....哈哈");}}}.start();
    

3. 多线程(获取当前线程的对象)(掌握) 【线程A与线程B 并发执行,顺序不定】

  带参的构造函数public Thread(String name)public Thread(Runnable target,String name)  
public static Thread currentThread()Thread.currentthread();——注意返回值是Thread//匿名内部类实现当前线程对象的获取
new Thread() {          public void run() {this.setName("线程A");for(int i = 0;i < 1000;i++) {System.out.println( Thread.currentThread().getName() + "....aaaa");}}}.start();匿名构造块作为参数new Thread(new Runnable() {public void run() {for(int i = 0;i < 1000;i++) {System.out.println( Thread.currentThread().getName() + "....bb");}}
},"线程B").start();       

}

4. 多线程(休眠线程)(掌握)

  • public static void sleep(long millis) throws InterruptedException

    • 抛出InterruptionException

        public class TestSleepOfThread {public static void main(String[] args) {Runnable r = ()->{try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Thread A");};new Thread(r).start();System.out.println("main Thread");}}/** 在JDK1.8中输出结果为:* -------------* main ThreadThread A-------------* */

5. 多线程(守护线程)(掌握)

  • setDaemon(), 设置一个线程为守护线程, 该线程不会单独执行, 当其他非守护线程都执行结束后, 自动退出

  • public final void setDaemon(boolean on)

    • on - if true, marks this thread as a daemon thread

        public class TestSetDaemon {public static void main(String[] args) {Thread t1 = new Thread("线程A") {public void run() {for(int i = 0;i < 2;i++) {System.out.println(Thread.currentThread().getName() + "....aaaa");}}};Thread t2 = new Thread(new Runnable() {public void run() {for(int i = 0;i < 50;i++) {System.out.println(Thread.currentThread().getName() + "....bb");}}},"线程B");将t2设置为守护线程t2.setDaemon(true);       //将t2设置为守护线程   t1.start();t2.start();}}/**  在JDK1.8中输出结果为:*  ------------------------*  线程A....aaaa线程B....bb线程A....aaaa线程B....bb      //存在时间缓冲问题线程B....bb线程B....bb线程B....bb线程B....bb线程B....bb线程B....bb* */
      

6. 多线程(加入线程)(掌握)

  • join(), 当前线程暂停, 等待指定的线程执行结束后, 当前线程再继续 

  •   t1.join();  当前线程暂停直到 线程t1执行完毕

  • join(int), 可以等待指定的毫秒之后  当前线程继续

  • public final void join() throws InterruptedException

      public class TestJoin {public static void main(String[] args) {Thread t1 = new Thread("线程A") {public void run() {for(int i = 0;i < 100;i++) {System.out.println(getName() + "....aaaaaaa");}}};Runnable r = ()->{for(int i = 0;i < 50;i++) {if(i == 2) {try {t1.join();  当前线程暂停知道 线程t1执行完毕//t1.join(1000); t1插队执行1秒后,t1和t2线程再抢占CPU交替执行} catch (InterruptedException e) {e.printStackTrace();}}               System.out.println(Thread.currentThread().getName() + "....bb");}};t1.start();new Thread(r).start();}}
    

13. 多线程(礼让线程)(了解)

  • yield让出cpu

14. 多线程(设置线程的优先级)(了解)

  • setPriority()设置线程的优先级

15. 多线程(同步代码块)(掌握)

  • 1.什么情况下需要同步
    • 当多线程并发, 有多段代码同时执行时, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作. 这时就需要同步.
    • 如果两段代码是同步的, 那么同一时间只能执行一段, 在一段代码没执行结束之前, 不会执行另外一段代码.
  • 2.同步代码块
    • 使用synchronized关键字加上一个锁对象来定义一段代码, 这就叫同步代码块

    • 锁对象不可以用匿名对象,因为匿名对象不是同一个对象

    • 多个同步代码块如果使用相同的锁对象, 那么他们就是同步的

        public class TestTickets_2 {public static void main(String[] args) {MyThread_6 myt = new MyThread_6();new Thread(myt,"线程A").start();new Thread(myt,"线程B").start();}}class MyThread_6 implements Runnable{private int ticket = 5;@Overridepublic void run() {while(true) {if(this.ticket > 0) {System.out.println(Thread.currentThread().getName() + "开始卖票 = " + ticket--);}else {System.out.println("票已经卖完");break;}}   }   }
      

16. 多线程(同步方法)(掌握)

public class TestSynchronized_2 {public static void main(String[] args) {Printer_2 p = new Printer_2();Runnable r = ()->{for(int i = 0;i < 100;i++) {p.print1();}};Thread t2 = new Thread() {public void run() {for(int i = 0;i < 100;i++) {p.print2();}}};new Thread(r).start();t2.start();     }
}class Printer_2{同步代码块public synchronized void print1() {System.out.print("早");System.out.print("上");System.out.print("好");System.out.print("啊");System.out.print("\r\n");}public void print2() {synchronized(this) {System.out.print("河");System.out.print("正");System.out.print("宇");System.out.print("好");System.out.print("帅");  System.out.print("\r\n");}       }   
}

17. 多线程(线程安全问题)(掌握)

  • 多线程并发操作同一数据时, 就有可能出现线程安全问题

  • 使用同步技术可以解决这种问题, 把操作数据的代码进行同步, 不要多个线程一起操作

      /**  铁路售票,一共100张,通过四个窗口卖完 * */public class TestSynchronized_3 {public static void main(String[] args) {new Ticket().start();new Ticket().start();new Ticket().start();}   }class Ticket extends Thread{private static int ticket = 100;public void run() {while(true) {//synchronized(this)synchronized(Ticket.class) {if(ticket == 0) {break;}System.out.println(getName() + "这是第" + ticket-- + "号票");}}}}
    

18. 多线程(火车站卖票的例子用实现Runnable接口)(掌握)

public class TestSynchronized_4 {public static void main(String[] args) {Ticket_2 t = new Ticket_2();new Thread(t,"线程A").start();new Thread(t,"线程B").start();new Thread(t,"线程C").start();new Thread(t,"线程D").start();}
}class Ticket_2 implements Runnable{private int ticket = 100;  //此时ticket不需要设置为共享,因为均为同一对象@Overridepublic void run() {while(true) {synchronized(this) {if(ticket == 0) {break;}System.out.println(Thread.currentThread().getName() + " 这是第" + ticket-- + "号票");}}}
}

19. 多线程(死锁)(了解)

public class TestDeadLock {private static Object o1 = new Object();private static Object o2 = new Object();public static void main(String[] args) {new Thread("线程A") {public void run() {while(true) {synchronized(o1) {System.out.println(getName() + "正在使用o1,等待o2");synchronized(o2) {System.out.println(getName()  +"等到o2,执行成功");}}}               }}.start();new Thread("线程B") {public void run() {while(true) {synchronized(o2) {System.out.println(getName() + "正在使用o2,等待o1");synchronized(o1) {System.out.println(getName() + "等到o1,执行成功");}}}               }}.start();}
}
/**  在JDK1.8中输出结果为:*  ----------------------线程A正在使用o1,等待o2线程A等到o2,执行成功线程A正在使用o1,等待o2线程B正在使用o2,等待o1-------------------------* */
  • 因此:synchronized不要嵌套使用,容易出错

20. 多线程和队列实现买卖票

Queue接口

public interface Queue {public void append(Object obj)throws Exception;public Object delete()throws Exception;public Object getFront()throws Exception;   public boolean isEmpty();
}

Class MyQueue

public class MyQueue implements Queue{//1 设置队列的默认长度static final int DEFAULT_SIZE=10;  //默认长度为10//2 设置队头int front; //3 设置队尾int rear;//4 定义统计元素的变量int count;//5 队的最大长度int maxSize;Object[] queue;  //设置队列//空构造public MyQueue() {this.init(DEFAULT_SIZE);  //用户给定长度 默认长度为10}//有参数的构造public MyQueue(int size) {this.init(size);  //开辟用户给定的长度}/*** 初始化方法* @param size*/public void init(int size) {//初始化属性this.maxSize=size;  //外部传进来的size//空队列front=rear=0;count=0;queue=new Object[size];}@Overridepublic void append(Object obj) throws Exception {// TODO Auto-generated method stub//首先队列是否已满if(count>0&&front==rear) {  //判断队列是否已满throw new Exception("队列已满");}this.queue[rear]=obj;rear=(rear+1)%maxSize;count++;}@Overridepublic Object delete() throws Exception {// TODO Auto-generated method stubif(this.isEmpty()) {throw new Exception("队列为空队");}Object obj=this.queue[front];front=(front+1)%maxSize;count--;return obj;}@Overridepublic Object getFront() throws Exception {// TODO Auto-generated method stubif(!this.isEmpty()) {return this.queue[front];}return null;}@Overridepublic boolean isEmpty() {// TODO Auto-generated method stubreturn this.count==0;}}

Class WindowQueue

public class WindowQueue { //卖票的窗口//定义卖票队列int maxSize=10;MyQueue queue=new MyQueue(maxSize);int num=0; //最多卖100张票boolean flag=true ; //判断是否继续卖票//排队买票public synchronized void producer()throws Exception{if(this.queue.count<maxSize) {this.queue.append(num++); //等待买票的数量++System.out.println("第"+num+"个客户排队买票");this.notifyAll(); //唤醒等待的线程}else {System.out.println("队列已满 请等待");this.wait(); }}//卖票public synchronized void consumer()throws Exception{if(this.queue.count>0) {Object obj=this.queue.delete();  //出队int temp=Integer.parseInt(obj.toString());System.out.println("第"+(temp+1)+"个客户买到票离开队列");//如果当前的队列为空 并且卖出票数大于100if(this.queue.isEmpty()&&this.num>=100) {this.flag=false;}this.notifyAll(); //唤醒等待的线程}else {System.out.println("队列已空 请等待");this.wait();}}
}

Class Producer

public class Producer implements Runnable{WindowQueue queue;public Producer(WindowQueue queue) {this.queue=queue;}@Overridepublic void run() {// TODO Auto-generated method stubwhile(queue.num<100) {  //必须小于100张票 才可以买票try {Thread.sleep(1000);queue.producer();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}

Class Consumer

public class Consumer implements Runnable{WindowQueue queue;public Consumer(WindowQueue queue) {this.queue=queue;}@Overridepublic void run() {// TODO Auto-generated method stubwhile(queue.flag) {  //如果队列为空 并且票数大于100 就不会卖票了try {Thread.sleep(1000);queue.consumer();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}

Class QueueTest

public class QueueTest {        public static void main(String[] args) throws Exception {       WindowQueue queue=new WindowQueue();Producer p=new Producer(queue);Consumer con=new Consumer(queue);//以上的代码一定要注意 传入的是同一个对象Thread t1=new Thread(p);Thread t2=new Thread(con);t1.start();t2.start();}
}

Lambda表达式

  • Lambda表达式的形式

    参数,箭头(→)以及一个表示

  • Lambda适用于接口中一个抽象方法时候使用

  • 举例1——函数式接口使用

      Runnable runner = ()->{StringBuffer s = new StringBuffer();for(int i= 0;i < 10;i++)System.out.println(s.append("haha"));};
    
  • 举例2——只有一个抽象方法的接口的实现类的使用

      Thread t1 = new Thread(()->{StringBuffer s = new StringBuffer();for(int i= 0;i < 10;i++)System.out.println(s.append("haha"));});
    
  • 区别于匿名内部类——需要写出方法声明

      new Thread(new Runnable() {public void run() {StringBuffer s = new StringBuffer();for(int i= 0;i < 10;i++)System.out.println(s.append("haha"));}           }).start(); Thread t1 = new Thread() {public void run() {StringBuffer s = new StringBuffer();for(int i= 0;i < 10;i++)System.out.println(s.append("haha"));}};


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

相关文章

java创建线程的四种方法

第一种: 通过继承Thread类创建线程 第二种: 通过实现Runnable接口创建线程 这两种早已烂记于心,这里就不作过多的介绍, 主要介绍其源码 Thread类 implements Runnable thread空线程的run方法 是判断target是否存在实,再执行target实例中的run方法 public void run(){if(th…

Java创建线程

目录 既然说到线程&#xff0c;在这里就给大家普及一下线程。 线程&#xff08;Thread&#xff09;&#xff1a; 那么&#xff0c;进程是什么呢&#xff1f; 接下来&#xff0c;就让我们步入主题&#xff1a; 在 Java 中&#xff0c;是这样说线程的&#xff1a; 创建一个新…

Java创建多线程的8种方式

目录 1、继承Thread类&#xff0c;重写run()方法 2、实现Runnable接口&#xff0c;重写run() 3、匿名内部类的方式 4、带返回值的线程(实现implements Callable<返回值类型>)————以上3种方式&#xff0c;都没有返回值且都无法抛出异常。 5、定时器(java.util.Timer)…

java如何创建线程

java如何创建线程 1. java如何创建线程1.1 通过继承Thread类来创建线程1.2 通过实现Runnable接口来创建线程1.3 通过匿名内部类来创建线程1.4 lambda表达式1.5 通过实现Runnable接口的方式创建线程目标类的优缺点 1. java如何创建线程 一个线程在Java中使用一个Thread实例来描…

Java多线程 - Java创建线程的4种方式

文章目录 1. Java创建线程有哪几种方式&#xff1f;1.1 线程创建方法一&#xff1a;继承Thread类创建线程类1.2 线程创建方法二&#xff1a;实现Runnable接口创建线程目标类1.5 线程创建方法三&#xff1a;使用Callable和FutureTask创建线程1.6 线程创建方法四&#xff1a;通过…

java创建线程的四种方式

1&#xff09;继承Thread类创建线程 如图所示: //继承Thread类 class Aclass extends Thread{//输出100以内的偶数Overridepublic void run() {for (int i 1; i <100; i) {System.out.println(getName()":"i);}} } 测试: Thread t1 new Aclass();t1.setName…

Java创建线程的七种方法,全网最全面总结~

目录 前言 一、继承Thread&#xff0c;重写run方法 二、实现Runnable接口&#xff0c;重写run方法 三、使用匿名内部类创建 Thread 子类对象 四、使用匿名内部类&#xff0c;实现Runnable接口 五、lambda表达式 六、实现Callable接口 七、使用线程池创建线程 前言 属于基…

java创建线程(Thread)的5种方式

java创建线程&#xff08;Thread&#xff09;的5种方式 方式一&#xff1a;继承于Thread类方式二&#xff1a;实现Runnable接口方式三&#xff1a;实现Callable接口方式四&#xff1a;使用线程池方式五&#xff1a;使用匿名类 方式一&#xff1a;继承于Thread类 步骤&#xff1…

前端开发与vscode开发工具介绍

文章目录 1、前端开发2、vscode安装和使用2.1、下载地址2.2、插件安装2.3、设置字体大小2.4、开启完整的Emmet语法支持2.5、创建项目2.6、保存工作区2.7、新建文件夹和网页 1、前端开发 前端工程师“Front-End-Developer”源自于美国。大约从2005年开始正式的前端工程师角色被…

IntelliJ IDE 插件开发指南

作者介绍 洪进锋&#xff0c;字节跳动后端研发工程师&#xff0c;参与过高并发系统&#xff08;百万QPS&#xff09;设计与研发工作。在开源项目方面混过 Sharding-JDBC 的 PR。个人开发的 IntelliJ IDE 插件 Redis Manager&#xff0c;目前在官方插件库中下载量 30K&#xff0…

真的要转到云IDE了吗?VS Code的开源IDE

云IDE产品介绍 云IDE使用教程 免费使用地址&#xff1a;点击【云IDE】&#xff0c;即可开始创建工作空间啦~ 前言 CSDN最新产品【云IDE】来啦&#xff01;【云IDE】将为各位技术er一键秒级构建云开发环境&#xff0c;提升开发效率&#xff01; 1. 什么是IDE&#xff1f; 做…

编辑器和IDE到底有什么区别呢?

其实很多接触了开发的工作人员都会接触以上 两种工具&#xff0c;编辑器&#xff0c;IDE。 其实我最刚开始的时候真的分不清&#xff0c;感觉都是开发的&#xff0c;上班以后呢慢慢就发现了两者的不同。 刚刚看知乎&#xff0c;发现一位哥们说话挺有意思的&#xff0c;比喻也…

初识Node.js之IDE的选择

其实就如同Java一样&#xff0c;Node可以选择的IDE不止一种&#xff0c;常见的比如webstorm&#xff0c;Visual Studio Code&#xff0c;其实都可以应付日常的工作需求&#xff0c;今天我要介绍的IDE&#xff0c;其实就是Visual Studio Code(接下来简称vs code)。怎么评价vs co…

【编辑器】VSCode的Web前端(html,css,JavaScript)开发环境打造

1、安装VScode和浏览器 VScode安装&#xff1a;https://code.visualstudio.com/ Chrome安装&#xff1a;https://www.google.com/intl/zh-CN/chrome/ node.js 安装&#xff1a;https://nodejs.org/zh-cn/download/ Web前端开发主要包括html&#xff0c;css&#xff0c;JavaScr…

IDE集成开发工具-IDEA(一)之IDE的概念

IDE的概念 集成开发环境&#xff08;IDE&#xff0c;Integrated Development Environment &#xff09;是用于提供程序开发环境的应用程序&#xff0c;一般包括代码编辑器、编译器、调试器和图形用户界面等工具。集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开…

11个裸VSCode必备插件,助你打造一个前端开发IDE

VSCode 轻量、开源&#xff0c;新鲜下载的 VSCode 可谓是身无长物、一穷二白&#xff0c;连个项目管理的功能都没有。 身轻如燕的 VSCode 对于后端开发说可能有点幼稚&#xff0c;但对于前端来说刚刚好&#xff0c;毕竟不需要搞什么 Docker、数据库等等&#xff0c;装俩 VSCod…

「干货」前端开发者最常用的六款IDE

微信公众号&#xff1a;javafirst 一、Visual Studio Code 下载地址&#xff1a;https://code.visualstudio.com/ 功能介绍&#xff1a; 微软在2015年4月30日Build 开发者大会上正式宣布了 Visual Studio Code 项目&#xff1a;一个运行于 Mac OS X、Windows和 Linux 之上的…

IDEA使用前端基础

常用快捷键和快捷语句 CtrlShiftEnter&#xff1a;将输入的if、for、函数等等补上{}或者;使代码语句完整 CtrlAltT&#xff1a;将选中的代码使用if、while、try/catch等包装 Alt/&#xff1a;自动完成 AltEnter&#xff1a;自动提示完成 Ctrl/&#xff1a;使用//进行注释 Ctrl…

IDE的详细介绍

IDE&#xff08;集成开发环境&#xff09; 就是电脑上编程时用的应用&#xff0c;比如&#xff1a;visual studio&#xff08;如图&#xff09;&#xff0c; eclipse等。IDE一般包括&#xff1a;代码编辑器、编译器、调试器和图形用户界面等工具。IDE是集成了代码编写功能、分…

IDE等开发工具的使用(VSCODE + IDEA)

Mac下各按键对应含义 ⌥ ⌃⇧⌘→ / ← ↑ / ↓ 各种快捷键的组合场景 左ctrl 待定 左alt cmd 待定 左ctrl shift 待定 左ctrl cmd 待定 左shift cmd 待定 1.熟悉的Mac下的快捷键&#xff08;持续补充&#xff09; 附&#xff1a;Vscode KeyShortCut 功能 快捷键 功能…