记录一次回客科技有关线程的笔试题,三个线程加法和一个线程减法 ,延申的两个线程交替执行

Posted liran123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记录一次回客科技有关线程的笔试题,三个线程加法和一个线程减法 ,延申的两个线程交替执行相关的知识,希望对你有一定的参考价值。

今天去了回客科技 笔试了一波。很遗憾啊,脑袋有思路 但是还没到手写代码很熟练的程度,基本功不到位。

第一道:线程的题:三个线程 +1 一个线程 -1 运算 。

看到网上还有四个线程的,两个加法计算,两个减法运算。基本的思路都是一样的 ,注意看同步处理。

下面贴出代码实现:

public class AddTest {


    private static int i;

    private static Object object = new Object();

    public static void main(String[] args) {
        
    
        new Thread(() -> {
            synchronized (object) {
                i++;
            }
        }).start();

        new Thread(() -> {
            synchronized (object) {
                i++;
            }

        }).start();

        new Thread(() -> {
            synchronized (object) {
                i++;
            }
        }).start();

        new Thread(() -> {
            synchronized (object) {
                i--;
            }
        }).start();
//这里睡眠 等所有线程运行完毕 看最终的数值,2 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i); } }



 这里引申出来了其他问题的思考

第1种:
synchronized void add 修饰普通方法 等同于
synchronized (this)
  public int i = 0;

    public void add(String threadName) {
        synchronized (this) {
            i++;
            System.out.println(threadName + "加法运算:" + i);
        }
    }

//上面代码等于如下代码:

   public synchronized void add(String threadName) {
  
            i++;
            System.out.println(threadName + "加法运算:" + i);
      
    }

  

第2种:
synchronized static void add 修饰静态方法 等同于
synchronized (*.class)

说明:以上两种我分析为 synchornized 修饰普通方法和this 对应的是同一个实例对象。而修饰静态方法和class 是对应的同一个类的 唯一的class对象。这个是我的理解,有错误之处请各位指正。在此谢过

第二道:
一个线程加一运算,一个线程做减法运算,多个线程同时交替运行(延申的)

第1种方法:使用Synchronized 实现
public class Count {
    private int num = 0;
    private boolean flag = false; // 标识

    //加法
    public synchronized void add() {
        while (flag) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.num++; //加
        System.out.println(Thread.currentThread().getName() + "........" + this.num);
        this.flag = true; //设置标识为true
        notifyAll(); //唤醒所有在线程池中冻结的线程,会把所有都唤醒

    }

    //减法
    public synchronized void sub() {
        while (!flag) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.num--; //减
        System.out.println(Thread.currentThread().getName() + "........" + this.num);
        this.flag = false; //设置标识为true
        notifyAll(); //唤醒所有在线程池中冻结的线程,会把所有都唤醒
    }
}

 第2种 :使用Lock 锁实现

 

public class CountLock {

    private int num = 0;
    private boolean flag = false; // 标识
    Lock lock = new ReentrantLock(); // 锁
    Condition add = lock.newCondition(); // 加法锁
    Condition sub = lock.newCondition();// 减法锁

    public void add() {
        lock.lock();// 锁上
        try {
            while (flag) {  //循环判断

                add.await();
            }
            this.num++;
            System.out.println(Thread.currentThread().getName() + "........" + this.num);
            this.flag = true; // 设置标识
            sub.signal(); // 唤醒指定线程
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void sub() {
        lock.lock();// 锁上
        try {
            while (!flag) {//循环判断
                sub.await();
            }
            this.num--;
            System.out.println(Thread.currentThread().getName() + "........" + this.num);
            this.flag = false; // 设置标识
            add.signal(); // 唤醒指定线程
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

  

调用的 main 方法:
    public static void main(String[] args) {
        //Count c=new Count();
        CountLock c=new CountLock();

        Thread t1=new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    c.add();
                }
            }
        });
        Thread t2=new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    c.sub();
                }

            }
        });

        t1.start();
        t2.start();
   //这里感觉线程少可以再启动 两个t3或者t4 来验证真实性

    }

  

这里延申的知识点参考博客:

java synchronized修饰普通方法,修饰静态方法,修饰代码块,修饰线程run方法 比较




















以上是关于记录一次回客科技有关线程的笔试题,三个线程加法和一个线程减法 ,延申的两个线程交替执行的主要内容,如果未能解决你的问题,请参考以下文章

多线程关于腾讯笔试题

某大型数据公司的笔试题

java 如何计算线程执行时间

笔试题-同线程Lock语句递归不会死锁

笔试题:创建三个线程,第一个线程打印1 2 3 4 5, 第二个线程打印 6 7 8 9 10...

异步和单线程