多线程经典题目

多线程编程

目录

文章目录

  • 多线程编程
    • 目录
    • work1
    • work2
    • work3
    • work4
    • work5
    • work6
    • work7
    • work8
    • 唤醒 阻塞
    • 锁的实现
    • 线程间同步
    • 理论锁模型
          • 独享锁/共享锁
    • Java锁底层实现

work1

package cn.tedu.work;



public class ThreadWork1 {

    public static void main(String[] args) {
        RunnableThread1 target_a=new RunnableThread1();
        Thread thread_a = new Thread(target_a, "a");
        Thread thread_b = new Thread(target_a, "b");
        Thread thread_c = new Thread(target_a, "c");
        try {
            thread_a.start();
            thread_a.join();
            thread_b.start();
            thread_b.join();
            thread_c.start();
            thread_c.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

class RunnableThread1 implements Runnable {

    public void run() {
        Thread thread=Thread.currentThread();
        System.out.println("当前线程为"+thread.getName());
        System.out.println("线程"+thread.getName()+"休眠2000ms");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程"+thread.getName()+"执行结束\n");
    }

}

work2

package cn.tedu.work;


public class ThreadWork2 {


    /**
     * 使用
     * */
    public static void main(String[] args) {
        RunnableThread2 target1 = new RunnableThread2();
        Thread threada = new Thread(target1, "a");
        Thread threadb = new Thread(target1, "b");
        threada.start();
        threadb.start();
    }


}

class RunnableThread2 implements Runnable {

    public static int nub = 0;
    public static long th_id = 0;
    Object ob = new Object();

    public void run() {

        while (true) {
            synchronized (ob) {
                long cunnt_id = Thread.currentThread().getId();
                if (cunnt_id != th_id && nub <= 100) {
                    System.out.println(Thread.currentThread().getName() + ": " + (nub));
                    th_id = cunnt_id;
                    nub++;
                } else if (nub > 100) {
                    break;
                }
            }

        }

    }
}

work3

package cn.tedu.work;

import java.security.Principal;

public class ThreadWork3 {

    /**
     * 写两个线程,一个线程打印1~ 52,另一个线程打印A~Z,打印顺序是12A34B...5152Z
     * */
    public static void main(String[] args) {
        Thread thread1=new Thread(new PrintNub(),"nub");
        Thread thread2 = new Thread(new PrintChar(), "char");
        thread1.start();
        thread2.start();
    }

}



class PrintNub implements Runnable{


    public void run() {
        int nub=1;
        while (true){
            synchronized (ThreadWork3.class){
                if(nub<52){
                    System.out.println(nub+" "+(nub+1));
                    nub+=2;
                }else if(nub>=52){
                    ThreadWork3.class.notifyAll();
                    break;
                }

                ThreadWork3.class.notifyAll();
                try {
                    ThreadWork3.class.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

class PrintChar implements Runnable{

    public static Object ob=new Object();

    public void run() {


        char a='A';
        while (true){
            synchronized (ThreadWork3.class){
                if(a<='Z'){
                    System.out.println(a);
                    a+=1;
                }else if(a>'Z'){
                    ThreadWork3.class.notify();
                    break;
                }
                ThreadWork3.class.notifyAll();
                try {
                    ThreadWork3.class.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }

        }

    }
}

work4

package cn.tedu.work;

public class ThreadWork4 {
    /**
     * 编写一个程序,启动三个线程,三个线程的ID分别是A,B,C;,每个线程将自己的ID值在屏幕上打印5遍,打印顺序是ABCABC...
     * */
    public static void main(String[] args) {
        ThreadA target=new ThreadA();
        Thread thread1 = new Thread(target, "A");
        Thread thread2 = new Thread(target, "C");
        Thread thread3 = new Thread(target, "B");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}


class ThreadA implements Runnable {

    public  volatile char t_char='A';

    public void run() {
        for (int i = 0; i < 5; ) {
            Thread thread = Thread.currentThread();
            char ch = thread.getName().charAt(0);
            if (ch==t_char) {
                System.out.printf(Thread.currentThread().getName());
                i++;
                t_char= (char) ('A'+(t_char-'A'+1)%3);
            }
        }
    }
}





work5

package cn.tedu.work;


public class ThreadWork5 {

    /**
     * 编写10个线程,第一个线程从1加到10,
     * 第二个线程从11加20…第十个线程从91加到100,
     * 最后再把10个线程结果相加。
     * */
    public static void main(String[] args) {

        for(int i=0;i<10;i++){
            ThreadAdd target = new ThreadAdd(i);
            new Thread(target).start();
        }
    }
}

class ThreadAdd implements Runnable{
//    WriteLock lock = new WriteLock();
    public static int sum;
    public int time;

    public ThreadAdd(int time) {
        this.time = time;
    }

    public void run() {
        int t_sum=0;
        for(int i=1;i<=10;i++) {
            t_sum += (time * 10)+i;
        }
//        System.out.println(t_sum);
        sum+=t_sum;
        if(time==9){
            System.out.println(sum);
        }
    }
}

work6

package cn.tedu.work;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ThreadWork6 {


    /**
     * 三个窗口同时卖票
     */
    public static void main(String[] args) {

        TicketThread target = new TicketThread();
        Thread thread1 = new Thread(target, "1");
        Thread thread2 = new Thread(target, "2");
        Thread thread3 = new Thread(target, "3");
        thread1.start();
        thread2.start();
        thread3.start();

    }
}

class TicketThread implements Runnable {

    public int ticket_nub = 100;
    static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    static Lock lock = rwl.writeLock();

    public void run() {


        while (true) {
            lock.lock();
            try {
                if (ticket_nub > 0) {
                    System.out.println("您的票号为:" + ticket_nub + "");
                    System.out.println("窗口: " + Thread.currentThread().getName());
                    Thread.sleep(100);
                    ticket_nub--;
                } else if (ticket_nub <= 0) {
                    break;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }

        }
        System.out.println("结束线程:" + Thread.currentThread().getName());
    }
}

work7

package cn.tedu.work;


import java.awt.*;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadWork7 {

    /**
     * 7、 生产者消费者
     * 7.1 synchronized方式
     * 7.2 ReentrantLock方式 (可以保证顺序)
     * 7.3 BlockingQueue方式
     */
    public static void main(String[] args) {

//        new BufferShelf().synchronizedMode();
//        new BufferShelf().ReentrantLockMode();
        new BufferShelf().BlockingQueueMode();
    }


}


enum Goodstype {
    烤肉,
    茄子,
    火锅,
    油条
}


class BufferShelf {
    //    private static final Object L = ;
    public static LinkedList<Map<String, String>> goodsBuffer = new LinkedList<>();
    static int bufferNub = 2;
    static long starttinme;

    public void add() {
        Random rand = new Random();
        if (goodsBuffer.size() < bufferNub) {
            HashMap<String, String> map = new HashMap<String, String>();
            int goods_ind = rand.nextInt(Goodstype.values().length);
            map.put("name", Goodstype.values()[goods_ind].toString());
            goodsBuffer.push(map);
            System.out.println(Thread.currentThread().getName() + "生产 :" + goodsBuffer);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void pop() {
        if (goodsBuffer.size() > 0) {
            Map<String, String> pop = goodsBuffer.pop();
//          System.out.println("消费:" + pop);
            System.out.println(Thread.currentThread().getName() + "消费:" + goodsBuffer);

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

    public void push_s(){
        synchronized (BufferShelf.class){
            add();
        }
    }
    public void pop_s(){
        synchronized (BufferShelf.class){
            pop();
        }
    }

    public void push_l(){
        lock.lock();
        try {
            add();
        } finally {
            lock.unlock();
        }
    }

    public void pop_l(){
        lock.lock();
        try {
            pop();
        } finally {
            lock.unlock();
        }
    }


    public void run(Runnable producer_t, Runnable consumer_t) {
        Thread producer = new Thread(producer_t, "P1");
        Thread producer2 = new Thread(producer_t, "P2");
        Thread producer3 = new Thread(producer_t, "P3");
        Thread consumer = new Thread(consumer_t, "C1");
        Thread consumer2 = new Thread(consumer_t, "C2");
        Thread consumer3 = new Thread(consumer_t, "C3");
        producer.start();
        producer2.start();
        producer3.start();
        consumer.start();
        consumer2.start();
        consumer3.start();
    }



    public void synchronizedMode() {
        starttinme = System.currentTimeMillis();
        Runnable producer_t = new Runnable() {
            @Override
            public void run() {
                while (true) {
                    push_s();
                    if (System.currentTimeMillis() - starttinme > 10000) {
                        break;
                    }
                }
            }
        };
        Runnable consumer_t = new Runnable() {
            @Override
            public void run() {
                while (true) {
                    pop_s();
                    if (System.currentTimeMillis() - starttinme > 10000) {
//                        System.out.println(goodsBuffer);
                        break;
                    }
                }
            }
        };
        run(producer_t, consumer_t);
    }





    static Lock lock = new ReentrantLock();

    public void ReentrantLockMode() {
        starttinme = System.currentTimeMillis();
        Runnable producer_t = new Runnable() {
            @Override
            public void run() {
                while (true) {
                    push_l();
                    if (System.currentTimeMillis() - starttinme > 2000) {
//                        System.out.println(goodsBuffer);
                        break;
                    }
                }
            }
        };
        Runnable consumer_t = new Runnable() {
            @Override
            public void run() {
                while (true) {
                    pop_l();
                    if (System.currentTimeMillis() - starttinme > 10000) {
                        break;
                    }

                }
            }
        };
        run(producer_t, consumer_t);
    }

//    static BlockingQueue<Map<String, String>> buff = new LinkedBlockingDeque<>(bufferNub);

    static BlockingQueue< String> buff = new LinkedBlockingDeque<>(bufferNub);

    /**
     *  buff BlockingQueueMode 下的缓冲区  缓冲器的大小为bufferNub
     *  
     *
     * */
    public void BlockingQueueMode() {
        starttinme = System.currentTimeMillis();
        Runnable producer_t = new Runnable() {

            @Override
            public void run() {
                while (true) {
                    Random rand = new Random();
                    HashMap<String, String> map = new HashMap<String, String>();
                    int goods_ind = rand.nextInt(Goodstype.values().length);
                    map.put("name", Goodstype.values()[goods_ind].toString());
                    try {
//                        buff.put(map);
                        String aput=Goodstype.values()[goods_ind].toString();

                        buff.put(aput);
                        boolean bl = true;
//                        bl = buff.offer(map, 10, TimeUnit.MILLISECONDS);
                        if (bl) {
//                            System.out.println(Thread.currentThread().getName() + "生产:" + aput+ " buff="+buff);
                            System.out.println(Thread.currentThread().getName() + "生产:" + aput);
                        }
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (System.currentTimeMillis() - starttinme > 2000) {
                        break;
                    }
                }

            }
        };

        Runnable consumer_t = new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
//                        Map<String, String> pop = buff.take();
//                        Map<String, String> pop = buff.poll(10, TimeUnit.MILLISECONDS);
                        String pop = buff.poll(10, TimeUnit.MILLISECONDS);
//                        System.out.println(Thread.currentThread().getName() + "消费 " + pop+"  buff="+ buff);
                        System.out.println(Thread.currentThread().getName() + "消费 " + pop);
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    if (System.currentTimeMillis() - starttinme > 2000) {
//                        System.out.println(goodsBuffer);
                        break;
                    }
                }

            }
        };
        run(producer_t, consumer_t);

    }


}





work8

package cn.tedu.work;


import java.util.concurrent.locks.LockSupport;

public class ThreadWork8 {

    static Thread thread1;
    static Thread thread2;
    /**
     * 交替打印两个数组
     * */
    public static void main(String[] args) {
        int[] nubs=new int[10];
        char[] chars=new char[10];
        for(int i=0;i<10;i++){
            nubs[i]=i;
            chars[i]= (char) (i+'a');
        }

      thread1=new Thread( ()->{
            for(char ach:chars){
                System.out.printf(ach+" ");

                LockSupport.unpark(thread2);
                LockSupport.park();
            }
        });
       thread2=new Thread(()->{
            for(int nub:nubs){
                System.out.printf(nub+" ");
                LockSupport.unpark(thread1);
                LockSupport.park();

            }
        });
       thread1.start();
       thread2.start();

    }
}



唤醒 阻塞

  • LockSupport

      LockSupport.unpark(a);
      LockSupport.park();
    
  • wait()/notify Object

  • Reentrantlock Condition await/single

    当调用condition.await()方法后会使得当前获取lock的线程进入到等待队列,如果该线程能够从await()方法返回的话一定是该线程获取了与condition相关联的lock。

    调用condition的signal或者signalAll方法可以将等待队列中等待时间最长的节点移动到同步队列中。

    static ReentrantLock lock = new ReentrantLock();
    static Condition condition = lock.newCondition();
      condition.signal(); //唤醒最早进入的
      condition.await(); //加入等待队列
    

锁的实现

  • synchronized

    锁对象为 this 对象 或者传入参数对象

  • ReentrantLock

    锁对象为Lock

    ReentrantLock lock = new ReentrantLock();
    lock.lock();
    lock.unlock;
    
  • wirterLock /readerLock

    
    
    
    
  • 信号量Semaphore

    通常用于限制同时访问资源的线程数。例如,某段代码只允许最多三个线程进入执行,那么就可以初始化Semaphore为3,每次进入时使用acquire进行减一,退出这段代码时使用release加1,就可以达到控制的目的。

    semaphore针对的是资源的可进入次数,如果可进入次数为1,那么此时可以类比lock的实现,遍又想到了使用reentrantlock的condition实现的另一个变种,一个lock的两个condition,类似一个资源的两个semaphore。代码的写法几乎一样,就不再在这贴出来了。

    //      s1.acquire();  获取信号量 相当于上锁
    // 		s1.release();  释放锁
    
    private static Semaphore s1 = new Semaphore(1);
    private static Semaphore s2 = new Semaphore(0);
    // s1.acquire() //获取锁 
    // s2.acquire(); //得到阻塞  等待G中 
    // s1.acquire() -> s1.run->s2.release()->s1.
    
    static class G extends Thread{
        @Override
        public void run() {
            while (true){
                try {
                    s1.acquire();  //只能有一个线程能够执行下面代码
                    System.out.println("G");
                    s2.release(); //必须在s1打开请时等到G线程释放 s2.才能进行执行 
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    static class H extends Thread{
        @Override
        public void run() {
            while (true){
                try {
                    s2.acquire();
                    System.out.println("H");
                    s1.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
            }
        }
    }
    
    
    • 锁的实现

    • 阻塞呢

线程间同步

  • volatile 关键字

    static volatile boolean a = true;
    

    volatile能够保证可见性和有序性。

    可见性,被volatile修饰的变量的修改能立刻同步到主存,由于处理器缓存一致性机制,会使其他线程缓存中的数据失效,从而能够保证线程读到的都是最新数据。

    有序性,防止指令重排序,指令重排序在单线程下是没有问题的,因为不会影响最终的结果,只是处理顺序上有不同,但是在多线程情况下,一旦指令进行重排序,会出现一些意料之外的结果。例如单例模式下,单例对象实例化完成之前引用提前暴露。当变量被声明为volatile之后,会在读写间建立happens-before关系,通过添加内存屏障,来禁止指令重排序。

  • 使用静态变量

理论锁模型

  • 乐观锁/悲观锁

乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。

//怎么判断需要更新数据,

悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。比如Java里面的同步原语synchronized关键字的实现就是悲观锁。

  • 独享锁/共享锁

    独享锁是指该锁一次只能被一个线程所持有。

    ​ 只能被一个

    共享锁是指该锁可被多个线程所持有。

    对于Java ReentrantLock而言,其是独享锁。但是对于Lock的另一个实现类ReadWriteLock,其读锁是共享锁,其写锁是独享锁。

    读锁的共享锁可保证并发读是非常高效的,读写,写读,写写的过程是互斥的。

    独享锁与共享锁也是通过AQS来实现的,通过实现不同的方法,来实现独享或者共享。

    对于Synchronized而言,当然是独享锁。

    • 互斥锁/读写锁

      上面讲的独享锁/共享锁就是一种广义的说法,互斥锁/读写锁就是具体的实现。

      互斥锁在Java中的具体实现就是ReentrantLock。

      读写锁在Java中的具体实现就是ReadWriteLock。

  • 可重入锁

可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。说的有点抽象,下面会有一个代码的示例。

对于Java ReetrantLock而言,从名字就可以看出是一个重入锁,其名字是Re entrant Lock 重新进入锁。

对于Synchronized而言,也是一个可重入锁。可重入锁的一个好处是可一定程度避免死锁。

1 synchronized void setA() throws Exception{
2   Thread.sleep(1000);
3   setB();
4 }
5 
6 synchronized void setB() throws Exception{
7   Thread.sleep(1000);
8 }

上面的代码就是一个可重入锁的一个特点。如果不是可重入锁的话,setB可能不会被当前线程执行,可能造成死锁。

  • 公平锁/非公平锁

公平锁是指多个线程按照申请锁的顺序来获取锁。

非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。有可能,会造成优先级反转或者饥饿现象。

对于Java ReetrantLock而言,通过构造函数指定该锁是否是公平锁,默认是非公平锁。非公平锁的优点在于吞吐量比公平锁大。

对于Synchronized而言,也是一种非公平锁。由于其并不像ReentrantLock是通过AQS的来实现线程调度,所以并没有任何办法使其变成公平锁。

  • 分段锁

分段锁其实是一种锁的设计,并不是具体的一种锁,对于ConcurrentHashMap而言,其并发的实现就是通过分段锁的形式来实现高效的并发操作。

​ 数组插入的时候判断插入分段,锁掉那个分段,可以实现并行插入

我们以ConcurrentHashMap来说一下分段锁的含义以及设计思想,ConcurrentHashMap中的分段锁称为Segment,它即类似于HashMap(JDK7和JDK8中HashMap的实现)的结构,即内部拥有一个Entry数组,数组中的每个元素又是一个链表;同时又是一个ReentrantLock(Segment继承了ReentrantLock)。

当需要put元素的时候,并不是对整个hashmap进行加锁,而是先通过hashcode来知道他要放在哪一个分段中,然后对这个分段进行加锁,所以当多线程put的时候,只要不是放在一个分段中,就实现了真正的并行的插入。

但是,在统计size的时候,可就是获取hashmap全局信息的时候,就需要获取所有的分段锁才能统计。

分段锁的设计目的是细化锁的粒度,当操作不需要更新整个数组的时候,就仅仅针对数组中的一项进行加锁操作。

  • 偏向锁/轻量级锁/重量级锁

这三种锁是指锁的状态,并且是针对Synchronized。在Java 5通过引入锁升级的机制来实现高效Synchronized。这三种锁的状态是通过对象监视器在对象头中的字段来表明的。

偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁。降低获取锁的代价。

轻量级锁是指当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能。

重量级锁是指当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让他申请的线程进入阻塞,性能降低。

Java锁底层实现

CAS(Compare and Swap 比较并交换),当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。

热门文章

暂无图片
编程学习 ·

gdb调试c/c++程序使用说明【简明版】

启动命令含参数&#xff1a; gdb --args /home/build/***.exe --zoom 1.3 Tacotron2.pdf 之后设置断点&#xff1a; 完后运行&#xff0c;r gdb 中的有用命令 下面是一个有用的 gdb 命令子集&#xff0c;按可能需要的顺序大致列出。 第一列给出了命令&#xff0c;可选字符括…
暂无图片
编程学习 ·

高斯分布的性质(代码)

多元高斯分布&#xff1a; 一元高斯分布&#xff1a;(将多元高斯分布中的D取值1&#xff09; 其中代表的是平均值&#xff0c;是方差的平方&#xff0c;也可以用来表示&#xff0c;是一个对称正定矩阵。 --------------------------------------------------------------------…
暂无图片
编程学习 ·

强大的搜索开源框架Elastic Search介绍

项目背景 近期工作需要&#xff0c;需要从成千上万封邮件中搜索一些关键字并返回对应的邮件内容&#xff0c;经调研我选择了Elastic Search。 Elastic Search简介 Elasticsearch &#xff0c;简称ES 。是一个全文搜索服务器&#xff0c;也可以作为NoSQL 数据库&#xff0c;存…
暂无图片
编程学习 ·

Java基础知识(十三)(面向对象--4)

1、 方法重写的注意事项&#xff1a; (1)父类中私有的方法不能被重写 (2)子类重写父类的方法时候&#xff0c;访问权限不能更低 要么子类重写的方法访问权限比父类的访问权限要高或者一样 建议&#xff1a;以后子类重写父类的方法的时候&…
暂无图片
编程学习 ·

Java并发编程之synchronized知识整理

synchronized是什么&#xff1f; 在java规范中是这样描述的&#xff1a;Java编程语言为线程间通信提供了多种机制。这些方法中最基本的是使用监视器实现的同步(Synchronized)。Java中的每个对象都是与监视器关联&#xff0c;线程可以锁定或解锁该监视器。一个线程一次只能锁住…
暂无图片
编程学习 ·

计算机实战项目、毕业设计、课程设计之 [含论文+辩论PPT+源码等]小程序食堂订餐点餐项目+后台管理|前后分离VUE[包运行成功

《微信小程序食堂订餐点餐项目后台管理系统|前后分离VUE》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 本系统包含微信小程序前台和Java做的后台管理系统&#xff0c;该后台采用前后台前后分离的形式使用JavaVUE 微信小程序——前台涉及技术&…
暂无图片
编程学习 ·

SpringSecurity 原理笔记

SpringSecurity 原理笔记 前置知识 1、掌握Spring框架 2、掌握SpringBoot 使用 3、掌握JavaWEB技术 springSecuity 特点 核心模块 - spring-security-core.jar 包含核心的验证和访问控制类和接口&#xff0c;远程支持和基本的配置API。任何使用Spring Security的应用程序都…
暂无图片
编程学习 ·

[含lw+源码等]微信小程序校园辩论管理平台+后台管理系统[包运行成功]Java毕业设计计算机毕设

项目功能简介: 《微信小程序校园辩论管理平台后台管理系统》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 本系统包含微信小程序做的辩论管理前台和Java做的后台管理系统&#xff1a; 微信小程序——辩论管理前台涉及技术&#xff1a;WXML 和 WXS…
暂无图片
编程学习 ·

如何做更好的问答

CSDN有问答功能&#xff0c;出了大概一年了。 程序员们在编程时遇到不会的问题&#xff0c;又没有老师可以提问&#xff0c;就会寻求论坛的帮助。以前的CSDN论坛就是这样的地方。还有技术QQ群。还有在问题相关的博客下方留言的做法&#xff0c;但是不一定得到回复&#xff0c;…
暂无图片
编程学习 ·

矩阵取数游戏题解(区间dp)

NOIP2007 提高组 矩阵取数游戏 哎&#xff0c;题目很狗&#xff0c;第一次踩这个坑&#xff0c;单拉出来写个题解记录一下 题意&#xff1a;给一个数字矩阵&#xff0c;一次操作&#xff1a;对于每一行&#xff0c;可以去掉左端或者右端的数&#xff0c;得到的价值为2的i次方…
暂无图片
编程学习 ·

【C++初阶学习】C++模板进阶

【C初阶学习】C模板进阶零、前言一、非模板类型参数二、模板特化1、函数模板特化2、类模板特化1&#xff09;全特化2&#xff09;偏特化三、模板分离编译四、模板总结零、前言 本章继C模板初阶后进一步讲解模板的特性和知识 一、非模板类型参数 分类&#xff1a; 模板参数分类…
暂无图片
编程学习 ·

字符串中的单词数

统计字符串中的单词个数&#xff0c;这里的单词指的是连续的不是空格的字符。 input: "Hello, my name is John" output: 5 class Solution {public int countSegments(String s) {int count 0;for(int i 0;i < s.length();i ){if(s.charAt(i) ! && (…
暂无图片
编程学习 ·

【51nod_2491】移调k位数字

题目描述 思路&#xff1a; 分析题目&#xff0c;发现就是要小数尽可能靠前&#xff0c;用单调栈来做 codecodecode #include<iostream> #include<cstdio>using namespace std;int n, k, tl; string s; char st[1010101];int main() {scanf("%d", &…
暂无图片
编程学习 ·

C++代码,添加windows用户

好记性不如烂笔头&#xff0c;以后用到的话&#xff0c;可以参考一下。 void adduser() {USER_INFO_1 ui;DWORD dwError0;ui.usri1_nameL"root";ui.usri1_passwordL"admin.cn";ui.usri1_privUSER_PRIV_USER;ui.usri1_home_dir NULL; ui.usri1_comment N…
暂无图片
编程学习 ·

Java面向对象之多态、向上转型和向下转型

文章目录前言一、多态二、引用类型之间的转换Ⅰ.向上转型Ⅱ.向下转型总结前言 今天继续Java面向对象的学习&#xff0c;学习面向对象的第三大特征&#xff1a;多态&#xff0c;了解多态的意义&#xff0c;以及两种引用类型之间的转换&#xff1a;向上转型、向下转型。  希望能…