Java多线程记录(包含案例)

线程是程序的执行单元,执行路径。是程序使用CPU的最基本单位

多线程 — 程序有多条执行路径,提高应用进程的使用率

进程中线程越多,抢到CPU执行权概率越高。线程的执行有随机性

Java程序的运行原理:

由Java命令启动JVM,JVM启动就相当于启动了一个进程,接着由该程序创建了一个主线程去调用main方法

JVM的启动是多线程的,因为垃圾回收线程也要启动,否则容易出现内存溢出。(GC线程和主线程)

Java多线程程序:

方法1:继承Thread类,并重写run()方法,创建对象,执行对象。

run()方法: Thread类中的run()用来包含那些被线程执行的代码(封装被线程执行的代码)(不单独调用run方法(直接调用是普通方法),调用start())

start()方法:首先启动了线程,然后再由JVM去调用该线程的run()方法

方法2:实现runnable接口

A:自定义类实现runnable

B:重写run()方法

C:创建MyRunnable类的对象

D:创建Thread类的对象,把C步骤的对象作为构造参数传递

解决了java单继承的局限性,适合多个相同程序代码去处理同一个资源的情况,把线程相同的代码,数据有效分离

一些内建方法:

public final String getName()   //获取线程名称
public final String setName():    //设置线程名称
public static Thread currentThread():    //返回当前正在执行的线程对象

抢占式调度模型(Java):优先让优先级高的线程使用CPU

public final int getPriority():   //返回线程对象的优先级
public final void setPriority(): //设置线程优先级

优先级范围1-10,默认为5,最低为1,最高为5

线程控制:

public static void sleep(long millis)    //线程休眠
public final void join():   //线程加入   (等待线程终止)
public static void yield():  //线程礼让 暂停当前正在执行的线程对象,并执行其他线程//让多个线程的执行更加和谐,但不能保证
public final void setDaemon(boolean on): //设置守护线程
//当正在运行的线程都是守护线程时,JVM退出,该方法必须在启动线程前调用
public void interrupt(): //中断线程,把线程的状态终止,并抛出一个InterruptException

线程的生命周期:(图解)

Java多线程记录(包含案例)

线程同步:synchronized关键字

将多条语句操作的共享数据代码包成一个整体,让某个线程在执行的时候别人不执行

前提:多个线程; 注意:多个线程使用同一个锁对象

优点:解决了多线程的安全问题

缺点:当线程相当时,因为每个线程都会去判断同步上的锁,很耗费资源,无形中降低了程序的运行效率,容易产生死锁

使用同步代码块或者同步方法

死锁:

死锁代码举例:

1 public class MyLock {
2     // 创建两把锁对象
3     public static final Object objA = new Object();
4     public static final Object objB = new Object();
5 }
1 public class DeadLock extends Thread {
 2
 3     private boolean flag;
 4
 5     public DeadLock(boolean flag) {
 6         this.flag = flag;
 7     }
 8
 9     @Override
10     public void run() {
11         if (flag) {
12             synchronized (MyLock.objA) {
13                 System.out.println("if objA");
14                 synchronized (MyLock.objB) {
15                     System.out.println("if objB");
16                 }
17             }
18         } else {
19             synchronized (MyLock.objB) {
20                 System.out.println("else objB");
21                 synchronized (MyLock.objA) {
22                     System.out.println("else objA");
23                 }
24             }
25         }
26     }
27 }
1 public class DieLockDemo {
2     public static void main(String[] args) {
3         DeadLock dl1 = new DeadLock(true);
4         DeadLock dl2 = new DeadLock(false);
5
6         dl1.start();
7         dl2.start();
8     }
9 }

等待唤醒机制:

Object类提供三个方法:

wait() :等待

notify():唤醒单个线程

notifyAll():唤醒所有线程

为什么不在Thread类中: 因为这些方法必须通过锁对象调用,而锁对象可以是任意锁对象,所以定义在object类中

Semaphore信号量:

信号量(Semaphore),又被称为信号灯,在多线程环境下用于协调各个线程, 以保证它们能够正确、合理的使用公共资源。信号量维护了一个许可集,我们在初始化Semaphore时需要为这个许可集传入一个数量值,该数量值代表同一时间能访问共享资源的线程数量。

线程可以通过acquire()方法获取到一个许可,然后对共享资源进行操作,注意如果许可集已分配完了,那么线程将进入等待状态,直到其他线程释放许可才有机会再获取许可,线程释放一个许可通过release()方法完成,”许可”将被归还给Semaphore。

多线程案例:

电影院卖票:电影院一共有100张票,有三个窗口卖票,模拟电影院售票:

使用同步代码块:

public class SellTicket implements Runnable {
    // 定义100张票
    private int tickets = 100;
    //创建锁对象
    private Object obj = new Object();

    @Override
    public void run() {
        while (true) {
            synchronized (obj) {
                if (tickets > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()
                            + "正在出售第" + (tickets--) + "张票");
                }
            }
        }
    }
}
public class SellTicketDemo {
    public static void main(String[] args) {
        // 创建资源对象
        SellTicket st = new SellTicket();

        // 创建三个线程对象
        Thread t1 = new Thread(st, "窗口1");
        Thread t2 = new Thread(st, "窗口2");
        Thread t3 = new Thread(st, "窗口3");

        // 启动线程
        t1.start();
        t2.start();
        t3.start();
    }
}

使用同步方法:

1 package lab2;
 2
 3 public class SellTicket implements Runnable {
 4
 5     // 定义100张票
 6     private static int tickets = 100;
 7
 8     @Override
 9     public void run() {
10         while (true) {
11             sellTicket();
12         }
13     }
14
15      private synchronized void sellTicket() {
16             if (tickets > 0) {
17             try {
18                     Thread.sleep(100);
19             } catch (InterruptedException e) {
20                     e.printStackTrace();
21             }
22             System.out.println(Thread.currentThread().getName()
23                         + "正在出售第" + (tickets--) + "张票 ");
24             }
25     }
26 }

使用锁方法:

1 import java.util.concurrent.locks.Lock;
 2 import java.util.concurrent.locks.ReentrantLock;
 3
 4 public class SellTicket implements Runnable {
 5
 6     // 定义票
 7     private int tickets = 100;
 8
 9     // 定义锁对象
10     private Lock lock = new ReentrantLock();
11
12     @Override
13     public void run() {
14         while (true) {
15             try {
16                 // 加锁
17                 lock.lock();
18                 if (tickets > 0) {
19                     try {
20                         Thread.sleep(100);
21                     } catch (InterruptedException e) {
22                         e.printStackTrace();
23                     }
24                     System.out.println(Thread.currentThread().getName()
25                             + "正在出售第" + (tickets--) + "张票");
26                 }
27             } finally {
28                 // 释放锁
29                 lock.unlock();
30             }
31         }
32     }
33
34 }

Ornamental Garden Problem:(使用Bakery class) 花园有两个旋转门,可进可出,监控花园内的人数

volatile关键字: Specifying a variable as volatile instructs the compiler to load and store the value of the variable at each use. 另外更多说明可以参考:https://www.cnblogs.com/daxin/p/3364014.html

Bakery Algorithm面包店算法

Bakery.java

 1 package lab2;
 2
 3 public class Bakery {
 4     public int nThreads;
 5
 6     private volatile int[] ticket;
 7     private volatile boolean[] choosing;
 8
 9     Bakery(int nTh) {
10         nThreads = nTh;
11         ticket = new int[nThreads];
12         choosing = new boolean[nThreads];
13
14         for (int i = 0; i < nThreads; i++) {
15             System.out.println(i + ticket[1]);
16             ticket[i] = 0;
17             choosing[i] = false;
18         }
19     }
20
21     private int getNextNumber() {
22         int largest = 0;
23         for (int i = 0; i < nThreads; i++) {
24             if (ticket[i] > largest)
25                 largest = ticket[i];
26         }
27         return largest + 1;
28     }
29
30     private boolean isFavouredThread(int i, int j) {
31         if ((ticket[i] == 0) || (ticket[i] > ticket[j]))
32             return false;
33         else {
34             if (ticket[i] < ticket[j])
35                 return true;
36             else
37                 return (i < j);
38         }
39     }
40
41     void wantToEnterCS(int threadID) {
42         choosing[threadID] = true;
43         ticket[threadID] = getNextNumber();
44         choosing[threadID] = false;
45
46         for (int otherThread = 0; otherThread < nThreads; otherThread++) {
47             while(choosing[otherThread]) {
48                 // busy-wait
49             }
50             // Break any ties between threads
51             while (isFavouredThread(otherThread,threadID)) {
52                 // busy-wait
53             }
54         }
55     }
56
57     void exitCS(int threadID) {
58         // Leave critical section
59         ticket[threadID] = 0;
60     }
61 }

Couter.java

1 package lab2;
 2
 3 public class Counter {
 4     volatile int value = 0;
 5
 6     Counter() {
 7         System.out.println("TOTAL: " + value);
 8     }
 9
10     boolean increment() {
11         int temp = value;   //read[v]
12         Simulate.HWinterrupt();
13         value = temp + 1;       //write[v+1]
14         System.out.println("TOTAL: " + value);
15             return true;
16     }
17
18     boolean decrement() {
19         int temp = value;   //read[v]
20         Simulate.HWinterrupt();
21             if (temp == 0) return false;
22         Simulate.HWinterrupt();
23         value = temp - 1;       //write[v+1]
24         System.out.println("TOTAL: " + value);
25             return true;
26     }
27 }
28
29 class Simulate {
30     public static void HWinterrupt() {
31         if (Math.random() < 0.5)
32            try{
33                Thread.sleep(200);
34            } catch(InterruptedException ie) {};
35     }
36 }

Turnstile.java

1 package lab2;
 2
 3 /* Notes:
 4  * No modifications need be made to the bakery class.  Instead, the turnstile
 5  * class and counter classes are adjusted to allow for "exit" turnstiles as well
 6  * as entrance turnstiles.  This solution incorporates a system to prevent the
 7  * number of people in the gardens from being negative, so the sleep call in
 8  * this class can be commented out.  Study the code in the Counter and Turnstile
 9  * classes to see how how this works.

10  * */
11
12 public class Gardens {
13      static Turnstile west;
14      static Turnstile east;
15      static Turnstile westExit;
16      static Turnstile eastExit;
17      static Counter people;
18      static Bakery bakery;
19
20     public static void main(String[] args) {
21         people = new Counter();
22         bakery = new Bakery(4);
23
24          west = new Turnstile(0, true, people, bakery);
25          east = new Turnstile(1, true, people, bakery);
26
27          westExit = new Turnstile(2, false, people, bakery);
28          eastExit = new Turnstile(3, false, people, bakery);
29
30          west.start();
31          east.start();
32
33         /*
34         try {
35             Thread.sleep(5000);
36         } catch (InterruptedException e) {
37         }
38         */
39
40         westExit.start();
41         eastExit.start();
42     }
43 }

Garden.java

1 package lab2;
 2
 3 public class Gardens {
 4      static Turnstile west;
 5      static Turnstile east;
 6      static Turnstile westExit;
 7      static Turnstile eastExit;
 8      static Counter people;
 9      static Bakery bakery;
10
11     public static void main(String[] args) {
12         people = new Counter();
13         bakery = new Bakery(4);
14
15          west = new Turnstile(0, true, people, bakery);
16          east = new Turnstile(1, true, people, bakery);
17
18          westExit = new Turnstile(2, false, people, bakery);
19          eastExit = new Turnstile(3, false, people, bakery);
20
21          west.start();
22          east.start();
23
24         /*
25         try {
26             Thread.sleep(5000);
27         } catch (InterruptedException e) {
28         }
29         */
30
31         westExit.start();
32         eastExit.start();
33     }
34 }

生产者消费者,操作列表:

Buffer.java

1 import java.util.LinkedList;
 2 import java.util.NoSuchElementException;
 3
 4 class Buffer {
 5     LinkedList queue = new LinkedList();
 6
 7     public synchronized void write(int i) {
 8         queue.add(i);
 9     }
10
11     public synchronized int read() {
12         try {
13             return queue.removeFirst();
14         } catch(NoSuchElementException e) {
15             // the buffer is empty!?

16             return -1;
17         }
18     }
19 }

Producer.java

1 class Producer implements Runnable {
 2     Buffer buffer;
 3
 4     public Producer(Buffer b) {
 5         buffer = b;
 6     }
 7
 8     public void run() {
 9         for(int i = 0; i < 20; i++) {
10             buffer.write(i);
11             System.out.println("Thread " + Thread.currentThread().getId() +
12                 " writes " + i);
13         }
14     }
15 }

Consumer.java

1 class Consumer implements Runnable {
 2     Buffer buffer;
 3
 4     public Consumer(Buffer b) {
 5         buffer = b;
 6     }
 7
 8     public void run() {
 9         for(int i = 0; i < 10; i++) {
10             try {
11                 Thread.sleep(10);
12             } catch (InterruptedException e) {
13             }
14             int x = buffer.read();
15             System.err.println("Thread " + Thread.currentThread().getId() +
16                 " reads " + x);
17         }
18     }
19 }

InfBuffer.java

1 public class InfBuffer {
 2     public static void main(String args[]) {
 3         Buffer b = new Buffer();
 4         Consumer c1 = new Consumer(b);
 5         Consumer c2 = new Consumer(b);
 6         Producer p = new Producer(b);
 7         (new Thread(c1)).start();
 8         (new Thread(c2)).start();
 9         (new Thread(p)).start();
10     }
11 }

生产者消费者,修改学生姓名和年龄并获取:(只能一打一大片,无法实现生产者生产后等待消费者消费后再产生)

1 public class Student {
2     String name;
3     int age;
4 }
1 public class SetThread implements Runnable {
 2
 3     private Student s;
 4     private int x = 0;
 5
 6     public SetThread(Student s) {
 7         this.s = s;
 8     }
 9
10     @Override
11     public void run() {
12         while (true) {
13             synchronized (s) {
14                 if (x % 2 == 0) {
15                     s.name = "Student1";
16                     s.age = 27;
17                 } else {
18                     s.name = "Student2";
19                     s.age = 30;
20                 }
21                 x++;
22             }
23         }
24     }
25 }
1 public class GetThread implements Runnable {
 2     private Student s;
 3
 4     public GetThread(Student s) {
 5         this.s = s;
 6     }
 7
 8     @Override
 9     public void run() {
10         while (true) {
11             synchronized (s) {
12                 System.out.println(s.name + "---" + s.age);
13             }
14         }
15     }
16 }
1 public class StudentDemo {
 2     public static void main(String[] args) {
 3         //创建资源
 4         Student s = new Student();
 5
 6         //设置和获取的类
 7         SetThread st = new SetThread(s);
 8         GetThread gt = new GetThread(s);
 9
10         //线程类
11         Thread t1 = new Thread(st);
12         Thread t2 = new Thread(gt);
13
14         //启动线程
15         t1.start();
16         t2.start();
17     }
18 }

生产者消费者,修改学生姓名和年龄并获取:(使用等待唤醒机制改进)

1 public class Student {
2     String name;
3     int age;
4     boolean flag;  //添加一个标记,默认为false,表示生产者是否生成值
5 }
1 public class SetThread implements Runnable {
 2
 3     private Student s;
 4     private int x = 0;
 5
 6     public SetThread(Student s) {
 7         this.s = s;
 8     }
 9
10     @Override
11     public void run() {
12         while (true) {
13             synchronized (s) {
14                 //判断有没有
15                 if(s.flag) {
16                     try {
17                         s.wait();
18                     } catch (InterruptedException e) {
19                         e.printStackTrace();
20                     }
21                 }
22
23                 if (x % 2 == 0) {
24                     s.name = "Student1";
25                     s.age = 27;
26                 } else {
27                     s.name = "Student2";
28                     s.age = 30;
29                 }
30                 x++;
31
32                 //修改标记
33                 s.flag = true;
34                 //唤醒线程
35                 s.notify();
36             }
37         }
38     }
49 }
1 public class GetThread implements Runnable {
 2     private Student s;
 3
 4     public GetThread(Student s) {
 5         this.s = s;
 6     }
 7
 8     @Override
 9     public void run() {
10         while (true) {
11             synchronized (s) {
12                 if (!s.flag) {
13                     try {
14                         s.wait();
15                     } catch (InterruptedException e) {
16                         e.printStackTrace();
17                     }
18                 }
19                 System.out.println(s.name + "---" + s.age);
20
21                 //修改标记
22                 s.flag = false;
23                 //唤醒线程
24                 s.notify();
25
26             }
27         }
28     }
29 }
public class StudentDemo {    //同上
    public static void main(String[] args) {
        //创建资源
        Student s = new Student();

        //设置和获取的类
        SetThread st = new SetThread(s);
        GetThread gt = new GetThread(s);

        //线程类
        Thread t1 = new Thread(st);
        Thread t2 = new Thread(gt);

        //启动线程
        t1.start();
        t2.start();
    }
}

厕所排队(使用信号量)

1 import java.util.Random;
 2 import java.util.concurrent.Semaphore;
 3
 4 class Wc extends Thread {
 5     private String name;
 6     private Semaphore wc;
 7
 8     public Wc(String name, Semaphore wc) {
 9         this.name = name;
10         this.wc = wc;
11     }
12
13     @Override
14     public void run() {
15         int availablePermit = wc.availablePermits();
16         if (availablePermit > 0) {
17             System.out.println(name+",好开心啊,我终于有坑了");
18         }else {
19             System.out.println(name+"怎么没有坑了。。。");
20         }
21
22         try {
23             wc.acquire();
24             System.out.println(name+",好开心啊,我终于抢到了!");
25             Thread.sleep(new Random().nextInt(1000));
26             System.out.println(name+",好爽啊,终于上完了!");
27             wc.release();
28         } catch (InterruptedException e) {
29
30         }
31     }
32 }
33
34 public class Demo {
35     public static void main(String[] args) {
36         Semaphore semaphore = new Semaphore(3);
37
38         for (int i = 0; i < 10; i++) {
39             Wc wc = new Wc("第"+i+"个人", semaphore);
40             wc.start();
41         }
42     }
43 }

The Sleeping Barber (生产者消费者,信号量)

1 import java.util.concurrent.Semaphore;
 2
 3 public class Barber implements Runnable{
 4
 5     Semaphore customerWaiting, seats, barberSleeping;
 6
 7     Barber(Semaphore customerWaiting, Semaphore seats, Semaphore barberSleeping) {
 8         this.customerWaiting = customerWaiting;
 9         this.seats = seats;
10         this.barberSleeping = barberSleeping;
11     }
12
13     public void run() {
14
15         while (true){
16
17             // Get a customer, sleep otherwise
18             try {
19                 customerWaiting.acquire();
20             } catch (InterruptedException e) {}
21
22             // Cut the hair of the customer
23             System.out.println("Cutting Hair");
24             barberSleeping.release();
25
26         }
27     }
28 }
1 import java.util.concurrent.Semaphore;
 2
 3 public class Customer implements Runnable{
 4
 5     Semaphore customerWaiting, seats, barberSleeping;
 6
 7     boolean cut = false;
 8     Customer(Semaphore customerWaiting, Semaphore seats, Semaphore barberSleeping) {
 9         this.customerWaiting = customerWaiting;
10         this.seats = seats;
11         this.barberSleeping = barberSleeping;
12
13     }
14
15     public void run() {
16         while (!cut) {
17
18             // A random delay
19             // Don't want all the threads trying at once!

20             try {
21                 Thread.sleep((long)(Math.random()*100));
22             } catch (InterruptedException e1) {}
23
24             // Try to get a seat in the waiting room
25             try {
26                 seats.acquire();
27             } catch (InterruptedException e) {}
28             System.out.println(seats.availablePermits());
29
30                 System.out.println(Thread.currentThread().getName()+" is sitting down");
31                 // Try and wake barber
32                 customerWaiting.release();
33
34
35                 // Get hair cut
36                 try {
37                     barberSleeping.acquire();
38                 } catch (InterruptedException e) {}
39                 cut = true;
40                 seats.release();
41
42         }
43         System.out.println(Thread.currentThread().getName()+" has had hair cut");
44     }
45 }
1 import java.util.concurrent.Semaphore;
 2
 3 public class Runner {
 4
 5     public static void main(String[] args) {
 6
 7         Semaphore barberSleeping = new Semaphore(1);
 8         Semaphore customerWaiting = new Semaphore(1);
 9         try {
10             customerWaiting.acquire();
11             barberSleeping.acquire();
12         } catch (InterruptedException e) {
13         }
14
15         Semaphore seats = new Semaphore(3);
16
17         Barber bar = new Barber(customerWaiting,seats,barberSleeping);
18         Thread bThread = new Thread(bar);
19         bThread.start();
20
21         int nCust = 30;
22         Customer customers[] = new Customer[nCust];
23         Thread cThread[] = new Thread[nCust];
24
25         for (int i=0;i) {
26              customers[i] = new Customer(customerWaiting,seats,barberSleeping);
27              cThread[i] = new Thread(customers[i]);
28              cThread[i].start();
29         }
30     }
31 }

线程池:

程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互,而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池

线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。

1 public class ExecutorsDemo {
 2     public static void main(String[] args) {
 3         // 创建一个线程池对象,控制要创建几个线程对象。
 4         // public static ExecutorService newFixedThreadPool(int nThreads)
 5         ExecutorService pool = Executors.newFixedThreadPool(2);        //直接通过类名调用
 6
 7         // 可以执行Runnable对象或者Callable对象代表的线程
 8         pool.submit(new MyRunnable());
 9         pool.submit(new MyRunnable());
10
11         //结束线程池
12         pool.shutdown();
13     }
14 }

使用Callable方法

public class MyCallable implements Callable {

    @Override
    public Object call() throws Exception {
        for (int x = 0; x < 100; x++) {
            System.out.println(Thread.currentThread().getName() + ":" + x);
        }
        return null;
    }

}
public class CallableDemo {
    public static void main(String[] args) {
        //创建线程池对象
        ExecutorService pool = Executors.newFixedThreadPool(2);

        //可以执行Runnable对象或者Callable对象代表的线程
        pool.submit(new MyCallable());
        pool.submit(new MyCallable());

        //结束
        pool.shutdown();
    }
}

Callable带返回值:

1 public class CallableDemo {
 2     public static void main(String[] args) throws InterruptedException, ExecutionException {
 3         // 创建线程池对象
 4         ExecutorService pool = Executors.newFixedThreadPool(2);
 5
 6         // 可以执行Runnable对象或者Callable对象代表的线程
 7         Future f1 = pool.submit(new MyCallable(100));
 8         Future f2 = pool.submit(new MyCallable(200));
 9
10         // V get()
11         Integer i1 = f1.get();
12         Integer i2 = f2.get();
13
14         System.out.println(i1);
15         System.out.println(i2);
16
17         // 结束
18         pool.shutdown();
19     }
20 }
1 public class MyCallable implements Callable {
 2
 3     private int number;
 4
 5     public MyCallable(int number) {
 6         this.number = number;
 7     }
 8
 9     @Override
10     public Integer call() throws Exception {
11         int sum = 0;
12         for (int x = 1; x ) {
13             sum += x;
14         }
15         return sum;
16     }
17
18 }

匿名内部类实现多线程:

1 public class ThreadDemo {
 2     public static void main(String[] args) {
 3         // 继承Thread类来实现多线程
 4         new Thread() {
 5             public void run() {
 6                 for (int x = 0; x < 100; x++) {
 7                     System.out.println(Thread.currentThread().getName() + ":"
 8                             + x);
 9                 }
10             }
11         }.start();
12
13         // 实现Runnable接口来实现多线程
14         new Thread(new Runnable() {
15             @Override
16             public void run() {
17                 for (int x = 0; x < 100; x++) {
18                     System.out.println(Thread.currentThread().getName() + ":"
19                             + x);
20                 }
21             }
22         }) {
23         }.start();
24
25         // 更有难度的
26         new Thread(new Runnable() {
27             @Override
28             public void run() {
29                 for (int x = 0; x < 100; x++) {
30                     System.out.println("hello" + ":" + x);
31                 }
32             }
33         }) {
34             public void run() {        //走的是这边的run方法
35                 for (int x = 0; x < 100; x++) {
36                     System.out.println("world" + ":" + x);
37                 }
38             }
39         }.start();
40     }
41 }

Original: https://www.cnblogs.com/AICROC/p/12813570.html
Author: 生于思考
Title: Java多线程记录(包含案例)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/643065/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • node使用es module

    https://www.npmjs.com/package/esm 作者:孟繁贵 Email:meng010387@126.com 期待共同进步! Original: https:…

    技术杂谈 2023年5月31日
    095
  • 说透缓存一致性与内存屏障

    https://www.cnblogs.com/chanmufeng/p/16523365.html Original: https://www.cnblogs.com/diyun…

    技术杂谈 2023年5月31日
    085
  • Servlet 4

    Servlet 4.0规约简介 Servlet 4.0 规约是JCP组织定义的Web规约,JSR编号369。 1.1 什么是Servlet? Servlet 是基于Java技术的W…

    技术杂谈 2023年7月25日
    069
  • Windows 10 MBR转GPT分区

    注意:分区有风险,操作需谨慎,提前备份好数据。 说明: 1、有”系统保留”的分区,可以直接删除,用来做GPT分区的UEFI启动分区。 2、没有”…

    技术杂谈 2023年5月31日
    069
  • 我们如何克服 Jenkins 声明式管道中长期运行的工作限制

    我们如何克服 Jenkins 声明式管道中长期运行的工作限制 – Camundahttps://camunda.com/blog/2022/02/how-we-over…

    技术杂谈 2023年6月1日
    0118
  • 2022.16 数字水印2

    安全技术包含3类:信息隐藏、访问控制和密码学。 典型的安全应用示例: 信息隐藏主要可分为隐写术和水印技术等两大类。隐写术的保护对象是隐秘消息,水印技术的保护对象是载体本身。 数字水…

    技术杂谈 2023年5月30日
    087
  • Axon框架快速入门和DDD项目实践

    Axon 框架是基于JVM平台的开源产品,由Allard Buijze于2009年创立。2017年7月,成立了一家独立公司AxonIQ,专门与Axon产品合作。 Axon 框架的程…

    技术杂谈 2023年6月1日
    089
  • java内存区域模型和详解

    一,概述 java虚拟机运行时数据区模型图: 主要包括:程序计数器,java虚拟机栈,本地方法栈,java 堆,方法区(元空间)。 其中堆和方法区由所有线程共享的数据区;程序计数器…

    技术杂谈 2023年7月11日
    070
  • Node安装与卸载命令汇总

    nvm(MAC管理node版本) 安装最新稳定版node: nvm install stable 安装指定版本: nvm install <version></v…

    技术杂谈 2023年6月21日
    083
  • 3_Spark Streaming DStream 及 算子

    1. 什么是 DStream ? 1. A Discretized Stream(一个离散化流) 2. Spark Streaming 中基本抽象 表示: 一系列 连续的 RDD …

    技术杂谈 2023年7月10日
    060
  • Mysql 事务(标贝科技)

    @ 事务 InnoDB对ACID的支持 隔离级别 + 不同隔离级别下读读取数据可能出现的情况 不可重复读和幻读区别 redo log (共享表空间) redo log block …

    技术杂谈 2023年7月25日
    089
  • 在Windows服务器上启用远程桌面连接

    按照以下的步骤来启用远程桌面连接,可以允许同时连接多人。 Step1:登录Windows 服务器””,打开”Start”(按下Win…

    技术杂谈 2023年5月31日
    084
  • 设计模式 08 代理模式

    代理模式(Proxy Pattern)属于 结构型模式 代理模式就是一个代理对象来间接访问对象,常用于无法直接访问某个对象或访问某个对象不方便的情况。 实际上代理在生活中处处都存在…

    技术杂谈 2023年7月25日
    061
  • 21级三翼技术部复试(前端)参考资料

    21级三翼技术部复试(前端)参考资料 一个目的是复习巩固一下,因为军训时发现脑中突然回忆不起来盒子模型了,感觉还是稍微敲一下会有印象,二是和大家一起分享交流一下,因为不保证每个答案…

    技术杂谈 2023年7月10日
    086
  • C语言建立哈夫曼树编码译码

    #include <stdio.h> #include <string.h> #include <stdlib.h> //&#x8F93…

    技术杂谈 2023年7月24日
    064
  • go日志

    go日志 go日志 // log package log //cxg 2022-7-29 import ( "log" "os" &quot…

    技术杂谈 2023年5月30日
    085
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球