精华内容
下载资源
问答
  • 三个Java多线程循环顺序周期打印1-75个数看到有这样一个关于并发的小题目,花了2分钟写一个demo问题的描述 启动3个线程打印递增的数字, 线程1先打印1,2,3,4,5, 然后是线程2打印6,7,8,9,10, 然后是线程3打印11,12,13...

    看到有这样一个关于并发的小题目,花了2分钟写一个demo

    问题的描述

    启动3个线程打印递增的数字, 线程1先打印1,2,3,4,5, 然后是线程2打印6,7,8,9,10, 然后是线程3打印11,12,13,14,15. 接着再由线程1打印16,17,18,19,20….以此类推, 直到打印到75. 程序的输出结果应该为

    package com.tiger
    
    import java.util.concurrent.atomic.AtomicInteger
    
    import akka.actor.{Actor, ActorLogging, ActorRef, ActorSystem, Props}
    
    object Print{
      val count = new AtomicInteger(0)
    }
    
    class Print extends Actor with ActorLogging{
    
      override def receive = {
    
        case (v1:ActorRef,v2:ActorRef) =>
          for(i <- 1 to 5){
            log.debug("{}",Print.count.incrementAndGet()
            //睡眠单纯为了适应线程调度
            TimeUnit.MILLISECONDS.sleep(100)
    
          }
          if(Print.count.get()<75){
            v1 ! (v2,self)
          }
      }
    
    }
    
    
    object T1 {
    
      def main(args: Array[String]): Unit = {
        val system = ActorSystem.create()
        val v1 = system.actorOf(Props[Print].withDispatcher("print-dispatcher"))
        val v2 = system.actorOf(Props[Print].withDispatcher("print-dispatcher"))
        val v3 = system.actorOf(Props[Print].withDispatcher("print-dispatcher"))
        v1 ! (v2,v3)
      }
    
    }
    

    application.conf

    print-dispatcher {
      type = Dispatcher
      executor = "thread-pool-executor"
      thread-pool-executor {
        fixed-pool-size = 3
      }
      throughput = 100
    }

    结果:

    [DEBUG] [09/05/2017 23:36:06.916] [main] [EventStream] StandardOutLogger started
    [DEBUG] [09/05/2017 23:36:07.300] [main] [EventStream(akka://default)] logger log1-Logging$DefaultLogger started
    [DEBUG] [09/05/2017 23:36:07.300] [main] [EventStream(akka://default)] logger log1-Logging$DefaultLogger started
    [DEBUG] [09/05/2017 23:36:07.302] [main] [EventStream(akka://default)] Default Loggers started
    [DEBUG] [09/05/2017 23:36:07.302] [main] [EventStream(akka://default)] Default Loggers started
    [DEBUG] [09/05/2017 23:36:07.343] [default-print-dispatcher-9] [akka://default/user/$a] 1
    [DEBUG] [09/05/2017 23:36:07.444] [default-print-dispatcher-9] [akka://default/user/$a] 2
    [DEBUG] [09/05/2017 23:36:07.545] [default-print-dispatcher-9] [akka://default/user/$a] 3
    [DEBUG] [09/05/2017 23:36:07.645] [default-print-dispatcher-9] [akka://default/user/$a] 4
    [DEBUG] [09/05/2017 23:36:07.745] [default-print-dispatcher-9] [akka://default/user/$a] 5
    [DEBUG] [09/05/2017 23:36:07.846] [default-print-dispatcher-11] [akka://default/user/$b] 6
    [DEBUG] [09/05/2017 23:36:07.946] [default-print-dispatcher-11] [akka://default/user/$b] 7
    [DEBUG] [09/05/2017 23:36:08.046] [default-print-dispatcher-11] [akka://default/user/$b] 8
    [DEBUG] [09/05/2017 23:36:08.146] [default-print-dispatcher-11] [akka://default/user/$b] 9
    [DEBUG] [09/05/2017 23:36:08.247] [default-print-dispatcher-11] [akka://default/user/$b] 10
    [DEBUG] [09/05/2017 23:36:08.347] [default-print-dispatcher-10] [akka://default/user/$c] 11
    [DEBUG] [09/05/2017 23:36:08.447] [default-print-dispatcher-10] [akka://default/user/$c] 12
    [DEBUG] [09/05/2017 23:36:08.547] [default-print-dispatcher-10] [akka://default/user/$c] 13
    [DEBUG] [09/05/2017 23:36:08.648] [default-print-dispatcher-10] [akka://default/user/$c] 14
    [DEBUG] [09/05/2017 23:36:08.748] [default-print-dispatcher-10] [akka://default/user/$c] 15
    [DEBUG] [09/05/2017 23:36:08.848] [default-print-dispatcher-9] [akka://default/user/$a] 16
    [DEBUG] [09/05/2017 23:36:08.948] [default-print-dispatcher-9] [akka://default/user/$a] 17
    [DEBUG] [09/05/2017 23:36:09.049] [default-print-dispatcher-9] [akka://default/user/$a] 18
    [DEBUG] [09/05/2017 23:36:09.149] [default-print-dispatcher-9] [akka://default/user/$a] 19
    [DEBUG] [09/05/2017 23:36:09.249] [default-print-dispatcher-9] [akka://default/user/$a] 20
    [DEBUG] [09/05/2017 23:36:09.350] [default-print-dispatcher-11] [akka://default/user/$b] 21
    [DEBUG] [09/05/2017 23:36:09.450] [default-print-dispatcher-11] [akka://default/user/$b] 22
    [DEBUG] [09/05/2017 23:36:09.550] [default-print-dispatcher-11] [akka://default/user/$b] 23
    [DEBUG] [09/05/2017 23:36:09.650] [default-print-dispatcher-11] [akka://default/user/$b] 24
    [DEBUG] [09/05/2017 23:36:09.751] [default-print-dispatcher-11] [akka://default/user/$b] 25
    [DEBUG] [09/05/2017 23:36:09.851] [default-print-dispatcher-10] [akka://default/user/$c] 26
    [DEBUG] [09/05/2017 23:36:09.951] [default-print-dispatcher-10] [akka://default/user/$c] 27
    [DEBUG] [09/05/2017 23:36:10.051] [default-print-dispatcher-10] [akka://default/user/$c] 28
    [DEBUG] [09/05/2017 23:36:10.152] [default-print-dispatcher-10] [akka://default/user/$c] 29
    [DEBUG] [09/05/2017 23:36:10.252] [default-print-dispatcher-10] [akka://default/user/$c] 30
    [DEBUG] [09/05/2017 23:36:10.352] [default-print-dispatcher-9] [akka://default/user/$a] 31
    [DEBUG] [09/05/2017 23:36:10.452] [default-print-dispatcher-9] [akka://default/user/$a] 32
    [DEBUG] [09/05/2017 23:36:10.553] [default-print-dispatcher-9] [akka://default/user/$a] 33
    [DEBUG] [09/05/2017 23:36:10.653] [default-print-dispatcher-9] [akka://default/user/$a] 34
    [DEBUG] [09/05/2017 23:36:10.753] [default-print-dispatcher-9] [akka://default/user/$a] 35
    [DEBUG] [09/05/2017 23:36:10.854] [default-print-dispatcher-11] [akka://default/user/$b] 36
    [DEBUG] [09/05/2017 23:36:10.954] [default-print-dispatcher-11] [akka://default/user/$b] 37
    [DEBUG] [09/05/2017 23:36:11.054] [default-print-dispatcher-11] [akka://default/user/$b] 38
    [DEBUG] [09/05/2017 23:36:11.154] [default-print-dispatcher-11] [akka://default/user/$b] 39
    [DEBUG] [09/05/2017 23:36:11.255] [default-print-dispatcher-11] [akka://default/user/$b] 40
    [DEBUG] [09/05/2017 23:36:11.355] [default-print-dispatcher-10] [akka://default/user/$c] 41
    [DEBUG] [09/05/2017 23:36:11.455] [default-print-dispatcher-10] [akka://default/user/$c] 42
    [DEBUG] [09/05/2017 23:36:11.555] [default-print-dispatcher-10] [akka://default/user/$c] 43
    [DEBUG] [09/05/2017 23:36:11.656] [default-print-dispatcher-10] [akka://default/user/$c] 44
    [DEBUG] [09/05/2017 23:36:11.756] [default-print-dispatcher-10] [akka://default/user/$c] 45
    [DEBUG] [09/05/2017 23:36:11.856] [default-print-dispatcher-9] [akka://default/user/$a] 46
    [DEBUG] [09/05/2017 23:36:11.956] [default-print-dispatcher-9] [akka://default/user/$a] 47
    [DEBUG] [09/05/2017 23:36:12.057] [default-print-dispatcher-9] [akka://default/user/$a] 48
    [DEBUG] [09/05/2017 23:36:12.157] [default-print-dispatcher-9] [akka://default/user/$a] 49
    [DEBUG] [09/05/2017 23:36:12.257] [default-print-dispatcher-9] [akka://default/user/$a] 50
    [DEBUG] [09/05/2017 23:36:12.358] [default-print-dispatcher-11] [akka://default/user/$b] 51
    [DEBUG] [09/05/2017 23:36:12.458] [default-print-dispatcher-11] [akka://default/user/$b] 52
    [DEBUG] [09/05/2017 23:36:12.558] [default-print-dispatcher-11] [akka://default/user/$b] 53
    [DEBUG] [09/05/2017 23:36:12.658] [default-print-dispatcher-11] [akka://default/user/$b] 54
    [DEBUG] [09/05/2017 23:36:12.759] [default-print-dispatcher-11] [akka://default/user/$b] 55
    [DEBUG] [09/05/2017 23:36:12.859] [default-print-dispatcher-10] [akka://default/user/$c] 56
    [DEBUG] [09/05/2017 23:36:12.959] [default-print-dispatcher-10] [akka://default/user/$c] 57
    [DEBUG] [09/05/2017 23:36:13.059] [default-print-dispatcher-10] [akka://default/user/$c] 58
    [DEBUG] [09/05/2017 23:36:13.160] [default-print-dispatcher-10] [akka://default/user/$c] 59
    [DEBUG] [09/05/2017 23:36:13.260] [default-print-dispatcher-10] [akka://default/user/$c] 60
    [DEBUG] [09/05/2017 23:36:13.360] [default-print-dispatcher-9] [akka://default/user/$a] 61
    [DEBUG] [09/05/2017 23:36:13.460] [default-print-dispatcher-9] [akka://default/user/$a] 62
    [DEBUG] [09/05/2017 23:36:13.561] [default-print-dispatcher-9] [akka://default/user/$a] 63
    [DEBUG] [09/05/2017 23:36:13.661] [default-print-dispatcher-9] [akka://default/user/$a] 64
    [DEBUG] [09/05/2017 23:36:13.761] [default-print-dispatcher-9] [akka://default/user/$a] 65
    [DEBUG] [09/05/2017 23:36:13.862] [default-print-dispatcher-11] [akka://default/user/$b] 66
    [DEBUG] [09/05/2017 23:36:13.962] [default-print-dispatcher-11] [akka://default/user/$b] 67
    [DEBUG] [09/05/2017 23:36:14.062] [default-print-dispatcher-11] [akka://default/user/$b] 68
    [DEBUG] [09/05/2017 23:36:14.162] [default-print-dispatcher-11] [akka://default/user/$b] 69
    [DEBUG] [09/05/2017 23:36:14.263] [default-print-dispatcher-11] [akka://default/user/$b] 70
    [DEBUG] [09/05/2017 23:36:14.363] [default-print-dispatcher-10] [akka://default/user/$c] 71
    [DEBUG] [09/05/2017 23:36:14.463] [default-print-dispatcher-10] [akka://default/user/$c] 72
    [DEBUG] [09/05/2017 23:36:14.563] [default-print-dispatcher-10] [akka://default/user/$c] 73
    [DEBUG] [09/05/2017 23:36:14.664] [default-print-dispatcher-10] [akka://default/user/$c] 74
    [DEBUG] [09/05/2017 23:36:14.764] [default-print-dispatcher-10] [akka://default/user/$c] 75

    从更高的角度看并发,将业务模型与底层系统分离,这或许是微服务的一个思路吧

    附源码

    展开全文
  • 将问题简化为3个线程无限循环打印1到3 方法一: 使用synchronized 三个线程无序竞争同步锁, 如果遇上的是自己的数字, 就打印. 这种方式会浪费大量的循环 1 2 3 4 5 6 7 8 9 ...

    要求

    启动N个线程, 这N个线程要不间断按顺序打印数字1-N. 将问题简化为3个线程无限循环打印1到3

    方法一: 使用synchronized

    三个线程无序竞争同步锁, 如果遇上的是自己的数字, 就打印. 这种方式会浪费大量的循环

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    public class TestSequential1 {

        private volatile int pos = 1;

        private volatile int count = 0;

     

        public void one(int i) {

            synchronized (this) {

                if (pos == i) {

                    System.out.println("T-" + i + " " + count);

                    pos = i % 3 + 1;

                    count = 0;

                } else {

                    count++;

                }

            }

        }

     

        public static void main(String[] args) {

            TestSequential1 demo = new TestSequential1();

            for (int i = 1; i <=3; i++) {

                int j = i;

                new Thread(()->{

                    while(true) {

                        demo.one(j);

                    }

                }).start();

            }

        }

    }

    输出

     

    T-1 0

    T-2 5793

    T-3 5285

    T-1 2616

    T-2 33

    T-3 28

    T-1 22

    T-2 44

    T-3 6

    T-1 881

    T-2 118358

    T-3 247380

    T-1 30803

    T-2 29627

    T-3 52044

    ...

     

    方法二: 使用synchronized配合wait()和notifyAll()

    竞争同步锁时使用wait()和notifyAll(), 可以避免浪费循环

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    public class TestSequential01 {

        private volatile int pos = 1;

        private volatile int count = 0;

        private final Object obj = new Object();

     

        public void run(int i) {

            int next = i % 3 + 1;

            while(true) {

                synchronized (obj) {

                    System.out.println(i + " in");

                    try {

                        while (pos != i) {

                            count++;

                            System.out.println(i + " wait");

                            obj.wait();

                        }

                        System.out.println("T-" + i + " " + count);

                        pos = next;

                        count = 0;

                        obj.notifyAll();

                    } catch (InterruptedException e) {

                        e.printStackTrace();

                    }

                }

            }

        }

     

        public static void main(String[] args) {

            TestSequential01 demo = new TestSequential01();

            for (int i = 3; i >=1; i--) {

                int j = i;

                new Thread(()->{

                    demo.run(j);

                }).start();

            }

        }

    }

    输出

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    3 in

    3 wait

    1 in

    T-1 1

    1 in

    1 wait

    2 in

    T-2 1

    2 in

    2 wait

    1 wait

    T-3 2

    3 in

    3 wait

    T-1 1

    1 in

    1 wait

    T-2 1

    2 in

    2 wait

    1 wait

    T-3 2

    3 in

    3 wait

    T-1 1

    1 in

    1 wait

     

    方法三: 使用可重入锁

    用Lock做, 非公平锁, 三个线程竞争, 如果遇上的是自己的数字, 就打印. 这种方式会浪费大量的循环

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    public class TestSequential01 {

        private final Lock lock = new ReentrantLock();

        private volatile int pos = 1;

        private volatile int count = 0;

     

        public void run(int i) {

            int next = i % 3 + 1;

            while(true) {

                lock.lock();

                if (pos == i) {

                    System.out.println("T-" + i + " " + count);

                    pos = next;

                    count = 0;

                } else {

                    count++;

                }

                lock.unlock();

            }

        }

     

        public static void main(String[] args) {

            TestSequential01 demo = new TestSequential01();

            for (int i = 1; i <=3; i++) {

                int j = i;

                new Thread(()->{

                    demo.run(j);

                }).start();

            }

        }

    }

    输出

    + View Code

     

    方法四: 使用可重入锁, 启用公平锁

    和3一样, 但是使用公平锁, 这种情况下基本上可以做到顺序执行, 偶尔会产生多一次循环

    1

    private final Lock lock = new ReentrantLock(true);

    输出

    + View Code

    .

    方法五: 使用Condition

    给每个线程不同的condition. 可以用condition.signal()精确地通知对应的线程继续执行(在对应的condition上await的线程, 可能是多个).

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    public class TestSequential01 {

        private static Lock lock = new ReentrantLock();

        private static Condition[] conditions = {lock.newCondition(), lock.newCondition(), lock.newCondition()};

        private volatile int state = 1;

     

        private void run(final int self) {

            int next = self % 3 + 1;

            while(true) {

                lock.lock();

                try {

                    while(this.state != self) {

                        conditions[self - 1].await();

                    }

                    System.out.println(self);

                    this.state = next;

                    conditions[next - 1].signal();

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

                lock.unlock();

            }

        }

     

        public static void main(String[] args) {

            TestSequential01 rlc = new TestSequential01();

            for (int i = 1; i < 4; i++) {

                int j = i;

                new Thread(()->rlc.run(j)).start();

            }

        }

    }

      

    总结

    在使用wait()和await()的竞争环境, 因为被notifyAll()和signal()之后到线程回到执行之前, 条件可能发生变化, 所以必须在wait()和await()外包使用while循环检测条件, 这是一个通用方法

    展开全文
  • 经典面试题编写一个程序,开启三个线程A,B,C , 这三个线程输出分别为 A、B、C,要求,按顺序输出ABC,循环10次, 分别为 ABCABCABCABCABC......下面介绍以下四种实现方式2.1 用synchronized、wait、notifyAll实现...

    经典面试题

    编写一个程序,开启三个线程A,B,C , 这三个线程输出分别为 A、B、C,要求,按顺序输出ABC,

    循环10次, 分别为 ABCABCABCABCABC......

    下面介绍以下四种实现方式

    2.1 用synchronized、wait、notifyAll实现

    标准的实现模式如下

    1、等待方遵循如下原则。

    (1) 获取对象的锁。

    (2) 如果条件不满足,那么调用对象的wait()方法,被通知后仍要检查条件。

    (3) 条件满足则执行对应的逻辑。

    synchronized(对象){

    while(条件不满足){

    对象.wait();

    }

    对应的处理逻辑;

    }

    2、通知方遵循如下原则。

    (1) 获得对象的锁。

    (2)改变条件。

    (3) 通知所有等待在对象上的线程。

    synchronized (对象){

    改变条件;

    对象.notifyAll();

    }

    实现代码如下:

    6555054cf960725b9cbff2633220f114.png
    41236bcd1e1cba91411425882bc80ec5.png

    测试结果:

    0be4c6f3e2d79bce688a364297182c6f.png

    实现步骤如下:

    1、线程定义每个线程执行的次数

    2、A B C 三个线程都需要先获取锁,无论谁先获取线程执行的优先权,Index 最初值为1,如果B 或者 C 先拿到执行权,则判断后,都会释放锁。最终会A拿到执行权。

    3、A执行后正好对index 取模 等于1,然后执行,唤醒B和C线程去执行

    4、B 和 C线程拿到执行权后,判断完成后,最终还是B得到执行

    5、依次循环下去

    2.2 用 ReentrantLock 和 Condition

    ReentrantLock 是可重入锁,支持公平和非公平锁。

    Condition 条件变量,对于每一个Lock,可以由任意数量的Condition对象,

    因此对于不同的条件谓词,对于同一锁,可以用不同的Condition 对象老控制。

    Condition 对象会继承相关的Lock公平性,对于公平的锁,线程会一招FIFO 顺序从await中释放。

    标准的写法如下:

    8689dc6b719c7fe3c5efec57cd8dd52c.png

    实现代码如下:

    bcd276d15203ed3f356ccfd2ff737723.png
    a4ad1a53a45d2729798e9f1ff8896033.png
    8b120a74f92351224a5e0cbea9ed2107.png

    测试结果:

    6a9e4bc7d711cd50e337652066519ece.png

    实现原理 和 2.1 类似。

    2.3 用 ReentrantLock 和 多个Condition

    Condition 能够更加精细的控制多线程的等待和唤醒,并且对于通过一个锁可以创建多个Condition监视器。

    利用不同的Condition对象实现当一个线程结束,唤醒下一个线程。

    使用volatile 修饰index, 可以在线程之间保持可见性。

    实现代码如下:

    56ab060ba193e5f87bd9d3da06ec42dd.png
    879c5cb45cb5df9253f023d8ad6d0bb1.png

    结果:

    4d2e571e00b8a76cbc44ff082fbd9a7a.png

    实现步骤:

    1、首先定义一个index区别每个线程。

    2、首先 A,B ,C 三个线程同时抢执行权,A的条件是index == 0,B 的条件是 index == 1,

    C的条件是 index == 1.

    3、满足条件后,依次进行唤醒。

    2.4 用 Semaphore 计数器

    Semaphore 是一个计数器信号量,必须由获取它的线程释放,通常用于限制可以访问某些资源。

    Semaphore方法如下:

    1. acquire: 方法阻塞,直到有一个许可证可以获取然后拿走一个租客正
    2. release: 增加一个许可证,然后释放一个阻塞acquire的方法

    下面用生活场景介绍

    比如××马路要限制流量,只允许同时有一百辆车在这条路上行驶,其他的都必须

    在路口等待,所以前一百辆车会看到绿灯,可以开进这条马路,后面的车会看到红灯,不能驶

    入××马路,但是如果前一百辆中有5辆车已经离开了××马路,那么后面就允许有5辆车驶入马

    路,这个例子里说的车就是线程,驶入马路就表示线程在执行,离开马路就表示线程执行完

    成,看见红灯就表示线程被阻塞,不能执行。

    8fe539aa999030a99aae3783235be88a.png

    实现代码如下:

    80cad233137ce5660fee4183ee456736.png
    c8b9e73ae6b3efd4161a158a1bc5c2c6.png

    结果为:

    56a3cb4549f044216cfc6c478e5c9def.png

    实现原理:

    1、首先让A有一个许可证,B C 默认为0个

    2、如果B或者C获取执行权,由于没有许可证,线程执行权会到A手中。

    3、A 执行后,由于有许可证,所以代码可以执行下去。执行完成后,增加B的许可证。

    4、B执行,执行完后,增加C的许可证,C执行完成后,增加A的许可证,A线程再次执行。

    如果你有不同的见解,欢迎评论!

    展开全文
  • 10 队列与多线程知识结构:图1 知识结构队列是我们经常使用的一种数据结构,如下图所示,购物结账,去食堂打饭等都需要排队,而结账或打饭的顺序与我们排队的顺序是相同的,即谁先排队就为谁先服务。图2 队列举例...

    22c70819ce1c37bed0573e79b39dbd4d.png

    10 队列与多线程

    知识结构:

    efdad7eb6b062dd1f1566a64d9718995.png
    图1 知识结构

    队列是我们经常使用的一种数据结构,如下图所示,购物结账,去食堂打饭等都需要排队,而结账或打饭的顺序与我们排队的顺序是相同的,即谁先排队就为谁先服务。

    768eca99328d8ddce6fe1c4ebd9857f1.png
    图2 队列举例

    比如我们发送邮件、打印资料,这些都是队列的具体应用。我们把需要发送的邮件先放到发送队列中,然后按照放入的顺序进行发送,把需要打印的文件先放到打印队列中, 然后按照放入的顺序进行打印。下面我们就来详细介绍“队列”这种数据结构。


    1. 队列的定义与操作

    1.1 队列的定义

    插入(入队)在一端(队尾)进行而删除(出队)在另一端(队首)进行的线性表。即先进先出(First In First Out)的线性表。

    【例子】线性表入队与出队演示。

    7bc38e72cc59fd0b372a06da8ac4ead2.png
    图3 顺序表模拟入队、出队
    5ea98d3fa05371c98a840b97364c751f.png
    图4 单链表模拟入队、出队

    1.2 队列的操作

    • 入队操作:将数据元素插入队尾。
    • 出队操作:移除队首的数据元素。
    • 是否为空:判断队中是否包含数据元素。
    • 得到队长:获取队中实际包含数据元素的个数。
    • 清空操作:移除队中的所有数据元素。
    • 获取队首元素。
    dc861086c2f187e0d3fc9f07945c4993.png
    图5 队列接口
    using System;

    2. 队列的顺序存储

    2.1 顺序队列

    顺序队列(Sequence Queue):利用顺序表实现的队列。

    实现:

    4f8b07fae3e2f03a376d396053d9c0ea.png
    图6 顺序队列
    using System;

    应用:

    class Program
    {

    2.2 循环队列

    循环队列(Circular Sequence Queue):利用数组采用循环的方式实现的队列。

    【例子】线性表入队与出队演示。

    050888dd4e2f78680da848cacd1ecdb2.png
    图7 循环队列过程演示

    实现:

    cf79b5f9b9562b491ca757a21198a664.png
    图8 循环队列
    using System;

    应用:

    class Program
    {

    3. 队列的链式存储

    链队:利用单链表实现的队列。

    利用单链表实现:

    950e6b8d0fd9d073a55e7781ffe5ae8b.png
    图9 链队
    using System;

    用单链表实现队列,入队时会进行链表的遍历操作,非常耗时。故实际应用中,链队常常用循环链表来实现。

    229627bbe7aabf1ddadb28b70585989f.png
    图10 链队
    using System;

    应用:

    class Program
    {

    4. 进程

    4.1 进程的定义

    进程是程序的动态执行过程,是操作系统进行资源分配和调度的基本单位。

    4.2 C# 对进程的管理

    我们通过一个具体的实例进行说明。

    b61cc5bfbf37b0abac9e171dcaabe016.png
    图11 进程实例

    (1)所在命名空间

    using System.Diagnostics;

    (2)进程的创建

    //初始化Process类的新实例。

    (3)进程的启动

    private void buttonStartNotepad_Click(object sender, EventArgs e){

    (4)进程的查询

    private void InitDataGridView(){

    (5)进程的终止

    private void buttonAbortNotepad_Click(object sender, EventArgs e){

    5. 线程

    5.1 线程的定义

    同一个进程又可划分为若干个独立的执行流称之为线程,线程是CPU进行资源分配和调度的基本单位。

    5.2 C#对线程的管理

    (1)所在命名空间

    using System.Threading;

    (2)线程的创建

    //初始化 Thread 类的新实例。

    (3)线程的启动

    //导致操作系统将当前实例的状态更改为 ThreadState.Running。

    (4)线程的休眠

    //将当前线程挂起指定的时间。该语句线程休眠1秒钟。

    (5)线程的合并

    //阻止调用线程,直到某个线程终止为止。

    (6)线程的终止

    //调用此方法通常会终止线程。

    【例子】没有共享资源的情况下两个线程的并行。

    static 

    客户端代码:

    class Program
    {
    a9f1f72c52a15879a1c8df344be16903.png
    图12 运行结果

    客户端代码:

    class Program
    {
    ccab7552a273c58484150a3f8fca0f3a.png
    图13 运行结果

    (7)线程的同步

    • 线程同步的定义
    c2b49774378c5cfffb41d1715849d29e.png
    图14 线程同步

    Thread1没有执行完临界区代码,分配的时间片结束,这时Thread2执行临界区代码,可能会产生错误。通常要求Thread1执行完临界区代码后,Thread2才能执行临界区代码。

    当两个或多个线程需要访问同一资源时,它们需要以某种顺序来确保该资源某一时刻只能被一个线程使用的方式称为 线程同步

    【例子】有共享资源的情况下不同步的例子。

    共享资源类:

    public 

    写线程执行的类:

    public 

    读线程执行的类:

    public 

    客户端代码:

    public 
    0233b599147ae47c3d3ddc5698008b83.png
    图15 运行结果
    • 利用lock关键字进行线程同步。

    用法:

    private 

    改进:

    public 
    e31a08e8dc37b39e5bba6db8628eb6aa.png
    图16 运行结果
    • 利用Monitor类进行线程同步。

    用法:

    private 

    该结构与lock关键字结构等价。

    public 
    e31a08e8dc37b39e5bba6db8628eb6aa.png
    图17 运行结果

    【例子】wThread线程写入数据后,rThread线程读取数据,交替进行。

    public 
    19425af4984059b8d85681a7b692cbf7.png
    图18 运行结果

    以下代码与上面代码等价:

    public 
    19425af4984059b8d85681a7b692cbf7.png
    图19 运行结果

    6. 队列的应用

    目前,在以银行营业大厅为代表的窗口行业中大量使用排队(叫号)系统,该系统完全模拟了人群排队全过程,通过取票进队、排队等待、叫号服务等功能,代替了人们站队的辛苦。

    1. 问题描述

    排队叫号软件的具体操作流程为:

    • 顾客取服务序号

    当顾客抵达服务大厅时,前往放置在入口处旁的取号机,并按一下其上的相应服务按钮,取号机会自动打印出一张服务单。单上显示服务号及该服务号前面正在等待服务的人数。

    • 服务员工呼叫顾客

    服务员工只需按一下其柜台上呼叫器的相应按钮,则顾客的服务号就会按顺序的显示在显示屏上,并发出“叮咚”和相关语音信息,提示顾客前往该窗口办事。当一位顾客办事完毕后,柜台服务员工只需按呼叫器相应键,即可自动呼叫下一位顾客。

    2. 问题分析

    编写程序模拟上面的工作过程,主要要求如下:

    • 程序运行后,当看到“请点击触摸屏获取号码:”的提示时,只要按回车键,即可显示“您的号码是:XXX,您前面有YYY位”的提示,其中XXX是所获得的服务号码,YYY是在XXX之前来到的正在等待服务的人数。
    • 用多线程技术模拟服务窗口(可模拟多个),具有服务员呼叫顾客的行为,假设每个顾客服务的时间是5000ms,时间到后,显示“请XXX号到ZZZ号窗口!”的提示。其中ZZZ是即将为客户服务的窗口号。

    3. 代码实现

    using System.Threading;

    客户端代码:

    class Program
    {

    4. 结果显示

    f5fdcf3f14ca637b57f96bfc980aa7ee.png
    图20 模拟结果

    2d1a5bb90263879ce52195add25a4421.png

    展开全文
  • 第四节 多线程更多练习题练习题1:三个线程交替打印数字启动3个线程打印递增的数字, 线程1先打印1,2,3,4,5 然后是线程2打印6,7,8,9,10 然后是线程3打印11,12,13,14,15.接着再由线程1打印16,17,18,19,20....依次类推,...
  • 第四节 多线程更多练习题练习题1:三个线程交替打印数字启动3个线程打印递增的数字, 线程1先打印1,2,3,4,5 然后是线程2打印6,7,8,9,10 然后是线程3打印11,12,13,14,15.接着再由线程1打印16,17,18,19,20....依次类推,...
  • 第四节 多线程更多练习题练习题1:三个线程交替打印数字启动3个线程打印递增的数字, 线程1先打印1,2,3,4,5 然后是线程2打印6,7,8,9,10 然后是线程3打印11,12,13,14,15.接着再由线程1打印16,17,18,19,20....依次类推,...
  • 题目是这样的:启动4个线程,第一个线程打印1,2;第二个线程打印3,4;第三个线程打印5,6;第四个线程打印7,8;然后第一个线程打印9,10...如此循环下去直到打印出100即终止. 刚拿这个题目的时候,觉得好简单啊(眼高手低.....
  • Python进阶--进程

    2020-11-10 07:40:02
    在 Python进阶教程m10–多线程 和 Python进阶教程m10b–多线程通信 我们学习了多线程编程,并行编程模式中还有一种多进程编程模式,这篇文件将介绍多进程编程。 1、编程模型 多进程需要用到multiprocessing...
  • (网络服务器、多线程、数据库、图像处理、多人聊天、等等) (2)音视频项目:包括编解码、视频监控、直播等各个方向,都需要亲手实战项目, 包括视频服务器、后台管理系统、前端播放器(多端) ------------------...
  • 多进程多线程综合实战读取CSV写入csv单线程统计行数多线程统计行数多进程统计行数多线程检索数据第一步多线程检索赵琳多线程检索找到通知其他人退出多线程检索开放数据并保存同一个文件作业day24up  多进程...
  • 4.1.5 字符串的打印 4 2 内存与链表 4 2.1 内存的分配与释放 4.2.2 使用LIST_ENTRY 4.2.3 使用长长整型数据 4.2.4 使用自旋锁 第5章 文件与注册表操作 5.1 文件操作 5.1.1 使片OBJECT_ATTRIBUTES 5.1.2 打开和关闭...
  • 从汇编语言Windows内核编程.pdf 【完整书签】【高清版】(共282页) ============================================ 入手篇 熟悉汇编 第1章 汇编指令与c语言 1.1 上机建立第一个工程 1.1.1用visual studio创建工程...
  • vc++ 应用源码包_1

    热门讨论 2012-09-15 14:22:12
    实现了自绘控件,云端控制主要在CnComm类多线程串口通讯库, camerads-DirectShow使用示例 演示了摄像头的使用 CatListBoxDemo ListBox控件与其它控件阙套使用方法 CCAMS系统是一种用于局域网下的CS模式的软件...
  • 17.5.5 多线程 17.5.6 IntelliTrace 17.6 重构工具 17.7 体系结构工具 17.7.1 依赖项关系图 17.7.2 层关系图 17.8 分析应用程序 17.8.1 代码地图 17.8.2 序列图 17.8.3 探查器 17.8.4 Concurrency Visualizer 17.8...
  • WPF编程宝典 part1

    2015-07-20 23:33:59
    19.3.2 项容器再循环 519 19.3.3 缓存长度 519 19.3.4 延迟滚动 520 19.4 验证 521 19.4.1 在数据对象中进行验证 521 19.4.2 自定义验证规则 526 19.4.3 响应验证错误 528 19.4.4 获取错误列表 529 19.4.5 显示不同...
  • 本书以其翔实知识面的覆盖、大量实用的示例和作者自身丰富的编程经验,阐述了从C语言编程基础、C++面向对象语法、MFC类库、控件及高级应用、进程和线程到异常处理等各个方面的诀窍,是一本系统而全面的编程经典图书...
  • 2.5.2 循环 2.5.3 跳转语句 2.6 枚举 2.7 数组 2.8 命名空间 2.8.1 using语句 2.8.2 命名空间的别名 2.9 Main()方法 2.9.1 个Main()方法 2.9.2 给Main()方法传送参数 2.10 有关编译C#文件的更内容 2.11 控制台I/...
  •  4.4.2 多线程程序的编写方式 93  4.5 小结 98  第5章 模拟做饭场景(线程的join()方法) 99  教学视频:7分钟  5.1 做饭场景原理 99  5.1.1 项目结构框架分析 99  5.1.2 项目功能业务分析 99 ...
  • 实例003 安装MSDN帮助编程学习 10 实例004 在VS 2008中设定断点及调试程序 13 1.2 应用Web.Config配置网站 16 实例005 配置Access数据库连接 16 实例006 配置SQL Server数据库连接 18 实例007 配置Session变量的生命...
  • 实例003 安装MSDN帮助编程学习 10 实例004 在VS 2008中设定断点及调试程序 13 1.2 应用Web.Config配置网站 16 实例005 配置Access数据库连接 16 实例006 配置SQL Server数据库连接 18 实例007 配置Session变量的生命...
  • 实例003 安装MSDN帮助编程学习 10 实例004 在VS 2008中设定断点及调试程序 13 1.2 应用Web.Config配置网站 16 实例005 配置Access数据库连接 16 实例006 配置SQL Server数据库连接 18 实例007 配置Session变量的生命...
  • 实例305 网络资源的多线程下载 478 实例306 下载网络资源的断点继传 480 第11章 TCP套接字 483 11.1 Socket基础 484 实例307 建立服务器套接字 484 实例308 建立客户端套接字 485 实例309 设置等待连接的超时时间 ...
  • 27.2.1 任务、线程和线程池 552 27.2.2 创建、运行和控制任务 553 27.2.3 使用task类实现并行处理 557 27.2.4 使用parallel类对任务进行抽象 564 27.2.5 什么时候不使用parallel类 568 27.2.6 从任务返回值 571...
  • 17.5.5 多线程 17.5.6 IntelliTrace 17.6 重构工具 17.7 体系结构工具 17.7.1 依赖项关系图 17.7.2 层关系图 17.8 分析应用程序 17.8.1 代码地图 17.8.2 序列图 17.8.3 探查器 17.8.4 Concurrency Visualizer 17.8...
  • 17.5.5 多线程 17.5.6 IntelliTrace 17.6 重构工具 17.7 体系结构工具 17.7.1 依赖项关系图 17.7.2 层关系图 17.8 分析应用程序 17.8.1 代码地图 17.8.2 序列图 17.8.3 探查器 17.8.4 Concurrency Visualizer 17.8...
  • 精易模块[源码] V5.15

    2015-03-21 22:03:37
    1、修正“编码_ansiusc2”当末尾出现10或13字符时出错的BUG,感谢易友【@rmcs】反馈。 2、改名“文件_搜索1”改为“文件_搜索_深度”并修正备注及深度问题,感谢易友【@小爬虫】反馈。 3、改善“时间_取现行时间戳...
  • 实例180 使用多线程制作端口扫描工具 343 实例181 使用线程扫描局域网ip地址 345 实例182 使用线程休眠控制图片以百叶窗效果显示 347 实例183 使用线程控制向窗体中拖放图片并显示 349 实例184 使用线程制作动画效果...
  • C# 2008编程参考手册

    热门讨论 2012-06-27 14:15:11
    ◆使用.NET Framework中的Thread类编写多线程应用程序的技术 ◆使用C#语言构建Windows、Web和Windows Mobile应用程序的方法 ◆构建Windows通信基础服务以及理解隐藏在这些服务背后的理论的方式 ◆使用Silverlight ...
  • 易语模块1000个

    2013-08-15 20:54:59
    2005-10-21 15:30 4303 1500 易语言模块大全\ACCSEE记录显示超级列表框模块.ec 2005-10-21 15:30 7198 2077 易语言模块大全\ACSII加解密模块2.0.ec 2005-10-21 15:30 25389 8592 易语言模块大全\AD.ec 2006-07-...

空空如也

空空如也

1 2 3 4 5
收藏数 100
精华内容 40
关键字:

多线程循环打印1到10