【Java基础总结】多线程

 1. 实现多线程的两种方式

 1 //第一种:继承Thread类,重写run()方法
 2 class ThreadTest1 extends Thread{
 3     public void run(){
 4         String threadName = Thread.currentThread().getName();
 5         for(int i=0;i<10;i++){
 6             System.out.println("ThreadTest1 "+threadName+" running ... "+i);
 7         }
 8     }
 9 }
10 
11 //第二种:实现Runnable接口,重写run()方法
12 class ThreadTest2 implements Runnable{
13     public void run(){
14         String threadName = Thread.currentThread().getName();
15         for(int i=0;i<10;i++){
16             System.out.println("ThreadTest2 "+threadName+" running ... "+i);
17         }
18     }
19 }

实现方式不同,使用方式也不同

public class Demo1{    public static void main(String[] args){ThreadTest1 t1 = new ThreadTest1();ThreadTest1 t2 = new ThreadTest1();Thread t3 = new Thread(new ThreadTest2());Thread t4 = new Thread(new ThreadTest2());t1.start();t2.start();t3.start();t4.start();}
}

运行结果大致如下:

ThreadTest1 Thread-0 running ... 0
ThreadTest2 Thread-3 running ... 0
ThreadTest2 Thread-2 running ... 0
ThreadTest1 Thread-1 running ... 0
ThreadTest2 Thread-2 running ... 1
ThreadTest2 Thread-3 running ... 1
ThreadTest1 Thread-0 running ... 1
ThreadTest2 Thread-3 running ... 2
ThreadTest2 Thread-2 running ... 2
ThreadTest1 Thread-1 running ... 1
ThreadTest2 Thread-2 running ... 3
ThreadTest2 Thread-3 running ... 3
ThreadTest1 Thread-0 running ... 2
ThreadTest2 Thread-3 running ... 4
ThreadTest2 Thread-2 running ... 4
ThreadTest1 Thread-1 running ... 2
ThreadTest2 Thread-2 running ... 5
ThreadTest2 Thread-3 running ... 5
ThreadTest1 Thread-0 running ... 3
ThreadTest2 Thread-3 running ... 6
ThreadTest2 Thread-2 running ... 6
ThreadTest1 Thread-1 running ... 3
ThreadTest2 Thread-2 running ... 7
ThreadTest2 Thread-3 running ... 7
ThreadTest2 Thread-3 running ... 8
ThreadTest2 Thread-3 running ... 9
ThreadTest1 Thread-0 running ... 4
ThreadTest1 Thread-0 running ... 5
ThreadTest2 Thread-2 running ... 8
ThreadTest2 Thread-2 running ... 9
ThreadTest1 Thread-1 running ... 4
ThreadTest1 Thread-0 running ... 6
ThreadTest1 Thread-0 running ... 7
ThreadTest1 Thread-0 running ... 8
ThreadTest1 Thread-1 running ... 5
ThreadTest1 Thread-0 running ... 9
ThreadTest1 Thread-1 running ... 6
ThreadTest1 Thread-1 running ... 7
ThreadTest1 Thread-1 running ... 8
ThreadTest1 Thread-1 running ... 9
View Code

 

2. 线程共享资源

建议使用 实现Runnable接口,重写run方法 的方式来实现多线程,它有如下优点:

1. 线程和代码分离,多线程间可以共享资源

2. 避免了单继承带来的局限性

3. 多线程之间可以共享资源

tip

Thread.currentThread().getName()  获得当前线程的名称
threadObj.setName()  设置线程名称

 

案例:售票

class ThreadTest4 implements Runnable{private int ticket=20;public void run(){String threadName = Thread.currentThread().getName();while(ticket>0){System.out.println("ThreadTest4 "+threadName+" 售出 "+ticket+" 号票");ticket--;}}
}

使用情况1:

     (new Thread(new ThreadTest4(), "窗口a")).start();(new Thread(new ThreadTest4(), "窗口b")).start();(new Thread(new ThreadTest4(), "窗口c")).start();(new Thread(new ThreadTest4(), "窗口d")).start();

运行情况说明A、B、C、D四个窗口也没用共享count这个资源

主线程名称:main
ThreadTest4 窗口a 售出 20 号票
ThreadTest4 窗口a 售出 19 号票
ThreadTest4 窗口b 售出 20 号票
ThreadTest4 窗口b 售出 19 号票
ThreadTest4 窗口b 售出 18 号票
ThreadTest4 窗口b 售出 17 号票
ThreadTest4 窗口b 售出 16 号票
ThreadTest4 窗口b 售出 15 号票
ThreadTest4 窗口a 售出 18 号票
ThreadTest4 窗口b 售出 14 号票
ThreadTest4 窗口d 售出 20 号票
ThreadTest4 窗口c 售出 20 号票
ThreadTest4 窗口d 售出 19 号票
ThreadTest4 窗口b 售出 13 号票
ThreadTest4 窗口a 售出 17 号票
ThreadTest4 窗口b 售出 12 号票
ThreadTest4 窗口d 售出 18 号票
ThreadTest4 窗口c 售出 19 号票
ThreadTest4 窗口d 售出 17 号票
ThreadTest4 窗口b 售出 11 号票
ThreadTest4 窗口a 售出 16 号票
ThreadTest4 窗口b 售出 10 号票
ThreadTest4 窗口d 售出 16 号票
ThreadTest4 窗口c 售出 18 号票
ThreadTest4 窗口d 售出 15 号票
ThreadTest4 窗口b 售出 9 号票
ThreadTest4 窗口a 售出 15 号票
ThreadTest4 窗口b 售出 8 号票
ThreadTest4 窗口d 售出 14 号票
ThreadTest4 窗口c 售出 17 号票
ThreadTest4 窗口d 售出 13 号票
ThreadTest4 窗口b 售出 7 号票
ThreadTest4 窗口a 售出 14 号票
ThreadTest4 窗口b 售出 6 号票
ThreadTest4 窗口d 售出 12 号票
ThreadTest4 窗口c 售出 16 号票
ThreadTest4 窗口d 售出 11 号票
ThreadTest4 窗口b 售出 5 号票
ThreadTest4 窗口a 售出 13 号票
ThreadTest4 窗口b 售出 4 号票
ThreadTest4 窗口d 售出 10 号票
ThreadTest4 窗口c 售出 15 号票
ThreadTest4 窗口d 售出 9 号票
ThreadTest4 窗口b 售出 3 号票
ThreadTest4 窗口a 售出 12 号票
ThreadTest4 窗口b 售出 2 号票
ThreadTest4 窗口d 售出 8 号票
ThreadTest4 窗口c 售出 14 号票
ThreadTest4 窗口d 售出 7 号票
ThreadTest4 窗口b 售出 1 号票
ThreadTest4 窗口a 售出 11 号票
ThreadTest4 窗口a 售出 10 号票
ThreadTest4 窗口d 售出 6 号票
ThreadTest4 窗口c 售出 13 号票
ThreadTest4 窗口d 售出 5 号票
ThreadTest4 窗口a 售出 9 号票
ThreadTest4 窗口d 售出 4 号票
ThreadTest4 窗口c 售出 12 号票
ThreadTest4 窗口d 售出 3 号票
ThreadTest4 窗口a 售出 8 号票
ThreadTest4 窗口d 售出 2 号票
ThreadTest4 窗口c 售出 11 号票
ThreadTest4 窗口d 售出 1 号票
ThreadTest4 窗口a 售出 7 号票
ThreadTest4 窗口c 售出 10 号票
ThreadTest4 窗口a 售出 6 号票
ThreadTest4 窗口a 售出 5 号票
ThreadTest4 窗口a 售出 4 号票
ThreadTest4 窗口a 售出 3 号票
ThreadTest4 窗口a 售出 2 号票
ThreadTest4 窗口a 售出 1 号票
ThreadTest4 窗口c 售出 9 号票
ThreadTest4 窗口c 售出 8 号票
ThreadTest4 窗口c 售出 7 号票
ThreadTest4 窗口c 售出 6 号票
ThreadTest4 窗口c 售出 5 号票
ThreadTest4 窗口c 售出 4 号票
ThreadTest4 窗口c 售出 3 号票
ThreadTest4 窗口c 售出 2 号票
ThreadTest4 窗口c 售出 1 号票
View Code

使用情况2:

    ThreadTest4 t2 = new ThreadTest4();(new Thread(t2,"窗口1")).start();(new Thread(t2,"窗口2")).start();(new Thread(t2,"窗口3")).start();(new Thread(t2,"窗口4")).start();

运行情况说明A、B、C、D四个窗口共享count这个资源(但发生了访问冲突)

主线程名称:main
ThreadTest4 窗口1 售出 20 号票
ThreadTest4 窗口2 售出 20 号票
ThreadTest4 窗口2 售出 19 号票
ThreadTest4 窗口2 售出 18 号票
ThreadTest4 窗口2 售出 17 号票
ThreadTest4 窗口2 售出 16 号票
ThreadTest4 窗口2 售出 15 号票
ThreadTest4 窗口2 售出 14 号票
ThreadTest4 窗口2 售出 13 号票
ThreadTest4 窗口2 售出 12 号票
ThreadTest4 窗口2 售出 11 号票
ThreadTest4 窗口2 售出 10 号票
ThreadTest4 窗口2 售出 9 号票
ThreadTest4 窗口2 售出 8 号票
ThreadTest4 窗口2 售出 7 号票
ThreadTest4 窗口3 售出 7 号票
ThreadTest4 窗口1 售出 5 号票
ThreadTest4 窗口2 售出 6 号票
ThreadTest4 窗口1 售出 3 号票
ThreadTest4 窗口4 售出 4 号票
ThreadTest4 窗口3 售出 4 号票
ThreadTest4 窗口1 售出 1 号票
ThreadTest4 窗口2 售出 2 号票
View Code

 

3. 线程同步

   多线程中涉及到共享数据时,会出现线程安全问题。就上面的售票案例来说,若没有加 synchronized 关键字,在多个线程同时使用ticket这个共享数据时,会出现同一个ticket被使用两次这样的看似不可能的情况。另外还有一种情况,事实上ticket这个共享数据是类ThreadTest4对象t2中的变量,所以若是在主线程中添加t2.run();语句的话,也是会发生线程安全问题的。

   在Java里面,同步锁的概念就是这样的。任何一个Object Reference都可以作为同步锁。我们可以把Object Reference理解为对象在内存分配系统中的内存地址。

 1 class ThreadTest5 implements Runnable{
 2     private int ticket=20;
 3     public void run(){
 4         while(ticket>0){        
 5             String threadName = Thread.currentThread().getName();
 6             //同步代码块(越小越好)
 7             synchronized(this){
 8                 if(ticket>0){
 9                     System.out.println(threadName + " sales ticket "+ticket);
10                     ticket--;
11                 }
12             }
13         }
14     }
15 }
16 
17 public class Demo3{
18     public static void main(String[] args){
19         ThreadTest5 t = new ThreadTest5();
20         (new Thread(t, "窗口A")).start();
21         (new Thread(t, "窗口B")).start();
22         (new Thread(t, "窗口C")).start();
23         (new Thread(t, "窗口D")).start();
24     }
25 }

运行结果

窗口A sales ticket 20
窗口A sales ticket 19
窗口A sales ticket 18
窗口A sales ticket 17
窗口A sales ticket 16
窗口A sales ticket 15
窗口A sales ticket 14
窗口A sales ticket 13
窗口A sales ticket 12
窗口A sales ticket 11
窗口A sales ticket 10
窗口D sales ticket 9
窗口D sales ticket 8
窗口D sales ticket 7
窗口D sales ticket 6
窗口D sales ticket 5
窗口D sales ticket 4
窗口D sales ticket 3
窗口C sales ticket 2
窗口B sales ticket 1
View Code

(1)同步代码块

synchronized(类或对象){//需要同步的代码段
}

(2)同步函数

(非static的情况)

public synchronized void fun(){//代码段
}

等价于(调用此同步函数的对象作为此同步函数的同步锁)

public void fun() {synchronized(this) {//代码段
    }
} 

(static的情况)

public static synchronized void fun() {//代码段
}

静态变量或静态方法加载到内存中时,内存中没有本类对象,但一定有了该类对应的字节码文件(类名.class),该对象的类型是class。静态同步函数使用的同步锁是所在类的字节码文件。

 

线程同步的前提:

  1)2个或2个以上的线程

  2)使用同一把锁
保证同步中只有一个线程在运行。

好处:解决线程安全问题
弊端:多个线程需要判断锁,消耗资源

 

4. 线程通信

经典的生产者和消费者问题

假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中的产品取走消费。如果仓库中没有产品,则生产者可以将产品放入仓库,否则停止生产并等待,直到仓库中的产品被消费者取走为止。如果仓库中放有产品,则消费者可以将产品取走消费,否则停止消费并等待,直到仓库中再次放入产品为止。显然,这是一个同步问题,生产者和消费者共享同一资源,并且,生产者和消费者之间彼此依赖,互为条件向前推进

4.1 synchronized和wait、notify、notifyAll

 wait() 使得当前线程必须要等待,并释放对锁的拥有权,等到另外一个线程调用notify()或者notifyAll()方法

 notify() 会唤醒一个等待当前对象的锁的线程

 notifyAll() 唤醒所有一个等待当前对象的锁的线程

一个小比较
  当线程调用了wait()方法时,它会释放掉对象的锁。
  另一个会导致线程暂停的方法:Thread.sleep(millisecond),它会导致线程睡眠指定的毫秒数,但线程在睡眠的过程中是不会释放掉对象的锁的。

 2     class Repository{
 3         private int count=0;        //当前仓库存放商品数量
 4         private int capacity=5;        //仓库容量
 5         private String goodsName;    //商品名称
 6         public Repository(String goodsName){
 7             this.goodsName = goodsName;
 8         }
 9         public void store(String threadName){
10             synchronized(this){
11                 while(this.count>=this.capacity){
12                     System.out.println("[" + threadName + "]仓库已达到最大容量 " + this.capacity + " 个 !!");
13                     try{this.wait();}
14                     catch(Exception e){}
15                 }
16                 this.count++;
17                 System.out.println("[" + threadName + "]仓库增加了一个"+this.goodsName+",现有"+this.goodsName+"["+this.count+"] 个");
18                 this.notifyAll();
19             }
20         }
21         public void fetch(String threadName){
22             synchronized(this){
23                 while(this.count<1){
24                     System.out.println("[" + threadName + "]仓库没有"+this.goodsName+"!!");
25                     try{
26                         this.wait();
27                     }catch(Exception e){
28                         
29                     }
30                 }
31                 this.count--;
32                 System.out.println("[" + threadName + "]仓库减少了一个"+this.goodsName+",现有"+this.goodsName+"["+this.count+"] 个");
33                 this.notifyAll();
34             }
35         }
36     }
37     //生产者
38     class Producter implements Runnable{
39         private Repository repository ;
40         public Producter(Repository repository){
41             this.repository = repository;
42         }
43         public void run(){
44             String threadName = Thread.currentThread().getName();
45             while(true){
46                 try{ 
47                     //sleep 2秒模拟生产过程
48                     Thread.sleep(1000); 
49                 }catch(Exception e){
50                     
51                 }
52                 //把生产的商品存放到仓库
53                 repository.store(threadName);
54             }
55         }
56     }
57     //消费者
58     class Consumer implements Runnable{
59         private Repository repository ;
60         public Consumer(Repository repository){
61             this.repository = repository;
62         }
63         public void run(){
64             String threadName = Thread.currentThread().getName();
65             while(true){
66                 //将商品从仓库取出来
67                 repository.fetch(threadName);
68                 try{ 
69                     //sleep 4秒模拟消费过程
70                     Thread.sleep(2000); 
71                 }catch(Exception e){
72                     
73                 }
74             }    
75         }
76     }
77     public class Thread06{
78         public static void main(String[] args){
79             Repository repository = new Repository("馒头");
80             
81             Producter pro1 = new Producter(repository);
82             Consumer con1 = new Consumer(repository);
83             //生产者和消费者各2个
84             (new Thread(pro1, "生产者A")).start();    
85             (new Thread(pro1, "生产者B")).start();
86             (new Thread(con1, "消费者1")).start();
87             (new Thread(con1, "消费者2")).start();
88         }
89     }

其中一种运行结果:

 1 [消费者1]仓库没有馒头!!
 2 [消费者2]仓库没有馒头!!
 3 [生产者A]仓库增加了一个馒头,现有馒头[1] 个
 4 [消费者2]仓库减少了一个馒头,现有馒头[0] 个
 5 [消费者1]仓库没有馒头!!
 6 [生产者B]仓库增加了一个馒头,现有馒头[1] 个
 7 [消费者1]仓库减少了一个馒头,现有馒头[0] 个
 8 [生产者A]仓库增加了一个馒头,现有馒头[1] 个
 9 [生产者B]仓库增加了一个馒头,现有馒头[2] 个
10 [生产者A]仓库增加了一个馒头,现有馒头[3] 个
11 [消费者2]仓库减少了一个馒头,现有馒头[2] 个
12 [生产者B]仓库增加了一个馒头,现有馒头[3] 个
13 [消费者1]仓库减少了一个馒头,现有馒头[2] 个
14 [生产者A]仓库增加了一个馒头,现有馒头[3] 个
15 [生产者B]仓库增加了一个馒头,现有馒头[4] 个
16 [消费者2]仓库减少了一个馒头,现有馒头[3] 个
17 [生产者A]仓库增加了一个馒头,现有馒头[4] 个
18 [消费者1]仓库减少了一个馒头,现有馒头[3] 个
19 [生产者B]仓库增加了一个馒头,现有馒头[4] 个
20 [生产者A]仓库增加了一个馒头,现有馒头[5] 个
21 [生产者B]仓库已达到最大容量 5 个 !!
22 [消费者2]仓库减少了一个馒头,现有馒头[4] 个
23 [生产者B]仓库增加了一个馒头,现有馒头[5] 个
24 [生产者A]仓库已达到最大容量 5 个 !!
25 [消费者1]仓库减少了一个馒头,现有馒头[4] 个
26 [生产者A]仓库增加了一个馒头,现有馒头[5] 个
27 [生产者B]仓库已达到最大容量 5 个 !!
28 [生产者A]仓库已达到最大容量 5 个 !!

(运行结果分析)

1)线程“消费者1”调用repositoy.fetch()方法去仓库取馒头。进入synchronized块,刚一执行while语句,结果 this.count<1 为真,直接就wait()进入等待队列,最后释放了锁
(就绪队列[消费者2,生产者A,生产者B],等待队列[消费者1]2)线程“消费者2”同“消费者1”的遭遇是相同的(对此,我们深表同情)
(就绪队列[生产者A,生产者B], 等待队列[消费者1,消费者2]3)线程“生产者A”生产完商品后,调用repository.store()方法把商品存到了仓库中。在store方法里,使用notifyAll方法唤醒了所有在沉睡wait的线程,最后释放了锁
(就绪队列[生产者A,生产者B,消费者1,消费者2],等待队列[]4)线程“消费者2”从上次wait的地方开始执行(从哪里跌倒,就从哪里爬起来)。同样是while语句,但这次 this.count<1 不为真了,于是乎顺利脱坑,接着执行 this.count--,把仓库仅有的一个馒头给拿走了,走之前还不忘大喊一句“仓库减少了一个馒头,现有馒头[0] 个”。同样是notifyAll方法唤醒所有沉睡wait的线程,释放锁
(就绪队列[生产者A,生产者B,消费者1,消费者2],等待队列[]5)线程“消费者1”辛辛苦苦抢到了锁,终于能执行syschronized块代码了。和“消费者2”一样,也是从上次wait的地方接着执行,也是while语句,但不同的是 this.count<1 为真,线程“生产者A”生产存放到仓库的仅有的一个馒头被“消费者2”给吃了,可以想象此时的“消费者1”心里是万念俱灰的。啥也别说了,接着沉睡wait吧。(释放了锁)
(就绪队列[生产者A,生产者B,消费者2],等待队列[消费者1])

**** 在接下来的几十个回合中,时而生产者线程夺得仓库锁,称霸武林,时而消费者线程夺得,笑傲江湖,仓库商品也是时增时减,但总体上还是生产者线程抢到的次数多,因为生产者够快,当消费者还在花2秒钟费劲的消化时,生产者早就1秒生产完毕,参与仓库锁的再次争夺了,可见“天下武功,唯快不破” *****“仓库里没有馒头为什么不通知我?”,线程“消费者2”不满“消费者1”对仓库情况的隐瞒不报,“你要是早告诉我,我也就不用争抢仓库锁,抢到了也没用,里面根本就没有馒头,去了也是wait”。(第1、2步) “你还有脸说我,你把生产者A生产存放在仓库仅有的一个馒头吃了,你明知道仓库再也没有馒头了,也不告诉我,还让我傻了吧唧抢到仓库锁,去了也白搭”。“消费者1”反驳道,它同样也很委屈。(第4、5步) “管我什么事,抢仓库锁的有不只你一个,我也去抢了,白费了劲,还没抢到
....”,线程“消费者2”道。“要是仓库没有馒头的时侯,只唤醒那帮生产者就好了”,线程“消费者1”和“消费者2”异口同声的说道。

处理线程通信必须遵循一种原则:对于生产者,在生产者没有生产之前,要通知消费者等待;在生产者生产之后,马上又通知消费者消费;对于消费者,在消费者消费之后,要通知生产者已经消费结束,需要继续生产新的产品以供消费。

4.2 Lock和Condition

Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition 对象。

Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用

 

5. 停止线程的方法

interrupt()        //停止线程
isInterrupt()     //判断线程是否停止

6. 守护线程和join方法

  守护线程是为其他线程提供便利服务的,当全部的用户线程结束后,守护线程才会随JVM结束工作。 thread.setDaemon(true); 

public static void main(String[] args){    Thread t3 = new Thread(test2, "线程t3");t3.start();t3.join();  //主线程就此陷入等待,直到t3线程结束。
}

7. 线程优先级和yield方法

线程的优先级从低到高:1-10,优先级高的的优先执行,每个新线程都继承了父线程的优先级,常量:Thread.MIN_PRIORITY 值为1,Thread.MAX_PRIORITY 值为10,Thread.NORM_PRIORITY 值为5

void setPriority(priority)    //设置线程优先级
int getPriority()            //获取线程优先级

 yield() 线程从执行状态变成就绪状态。

 

转载于:https://www.cnblogs.com/lhat/p/6819170.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/400378.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++类分号(;)问题

环境&#xff1a;vs2010 问题&#xff1a;今天编代码过程中发现好多很奇怪的错误&#xff0c;我以为昨天调了下编译器才出问题了。搞了好久&#xff0c;代码注释掉很多还是不行,并且错误还一直在变化。问题大概如下&#xff1a; &#xff08;照片上传不了&#xff09; 1.error …

PHP远程连接MYSQL数据库非常慢的解决方法

不知道如何解决&#xff0c;所以把他空间所在的服务器上也装了个MYSQL,才解决问题&#xff0c;今天又有个这个问题&#xff0c;不能也在这服务器上装一个MYSQL吧&#xff0c;Search: PHP远程连接MYSQL速度慢,有时远程连接到MYSQL用时4-20秒不等,本地连接MYSQL正常,出现这种问题…

【51单片机快速入门指南】5:软件SPI

目录硬知识SPI协议简介SPI接口介绍SPI接口连接图SPI数据传输方向SPI传输模式软件SPI程序源码Soft_SPI.cSoft_SPI.h普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 上位机&#xff1a;Vofa 1.3.10 源于软件模拟SPI接口程序代码&…

svn搭建本地服务端

使用VisualSVN Server来完成,下载地址:https://www.visualsvn.com/server/download/ 我安装的版本是3.3.1,安装的时候选择了标准版本&#xff0c;另外一个版本需要付费(日志跟踪、VDFS等功能)更多可以参考https://www.visualsvn.com/server/licensing/安装完成之后&#xff0c;…

hdu 4612 边连通度缩点+树的最长路径

思路&#xff1a;将以桥为分界的所有连通分支进行缩点&#xff0c;得到一颗树&#xff0c;求出树的直径。再用树上的点减去直径&#xff0c;再减一 #pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #incl…

c++ primer 4.4节练习答案

练习4.13 a) d3.0, i3 b) i3, d3.5 练习4.14 第一个&#xff1a;非法&#xff0c;42是一个右值&#xff0c;右值不能当做左值使用 第二个&#xff1a;返回值总为真 练习4.15 pi是指针类型&#xff0c;不可将int类型指针赋值给int型&#xff0c;可做如下修改 dval ival 0; pi …

详解Ubuntu Server下启动/停止/重启MySQL数据库的三种方式(ubuntu 16.04)

启动mysql&#xff1a; 方式一&#xff1a;sudo /etc/init.d/mysql start 方式二&#xff1a;sudo service mysql start 停止mysql&#xff1a; 方式一&#xff1a;sudo /etc/init.d/mysql stop 方式二&#xff1a;sudo service mysql stop 重启mysql&#xff1a; 方式一…

【51单片机快速入门指南】5.1:SPI与DS1302时钟芯片

目录硬知识DS1302 简介DS1302 使用控制寄存器日历/时钟寄存器DS1302 的读写时序电路设计示例程序DS1302.cDS1302.h测试程序main.c实验现象普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 硬知识 摘自《普中 51 单片机开发攻略》…

006_Select.sql查询语句

--创建一个部门表 CREATE TABLE tb2_dapt(DEPTNO INT PRIMARY KEY, --部门编号DNAME VARCHAR(20) NOT NULL, --部门名称LOC VARCHAR(20) NOT NULL --部门地址 ) --插入数据 INSERT INTO tb2_dapt (DEPTNO, DNAME, LOC) VALUES(10,财务部,北京); INSERT INTO tb2_dapt (DEPTN…

【格局视野】三色需求与工作层次

三色需求 人们的社会经济生活本身就是一个互相交换&#xff0c;价值传递的循环&#xff0c;但这个循环有一个核心&#xff0c;这个核心就是社会大众的需求&#xff0c;也可以称为市场需求&#xff0c;围绕这个需求产生了层级递进的需求关系。 第一个层次是蓝色需求 是最基础的社…

关于linux-Centos 7下mysql 5.7.9的rpm包的安装方式

环境介绍>>>>>>>>>>>>>>>>>> 操作系统&#xff1a;Centos 7.1 mysql数据库版本&#xff1a;mysql5.7.9 mysql官方网站&#xff1a;http://www.mysql.com 原文地址&#xff1a;http://www.cnblogs.com/5201351/p/4912614…

【51单片机快速入门指南】5.2:SPI读取 12位ADC XPT2046 芯片

目录硬知识ADC 简介分辨率转换误差转换速率ADC 转换原理逐次逼近型 ADC双积分型 ADCXPT2046 芯片介绍参考电压内部参考电压外部参考电压输入工作模式单端工作模式差分工作模式温度测量电池电压测量压力测量数字接口笔中断输出转换周期16 时钟周期转换数字时序15 时钟周期转换数…

flask中 app.run(host='0.0.0.0', port=5000, debug=False) 不能用外网ip访问的解决办法

pycharm 2018开启debug模式和修改host&#xff1a; 在Pycharm 2018中&#xff0c;如果想要开启debug模式和更改端口号&#xff0c;则需要编辑项目配置。直接在app.run中更改是无效的。示例图如下&#xff1a; 将 app.run() 改成 app.run(debugFalse) 保存文件&#xff0c…

开发第一个spring boot应用

为什么80%的码农都做不了架构师&#xff1f;>>> 我们来用spring boot开发一个简单的“hello world”web应用&#xff0c;使用maven构建。开始之前&#xff0c;先检查你的java与maven的版本&#xff0c;看是否是spring boot1.3支持的版本&#xff1a; $ java -versi…

机器学习中规则化和模型选择知识

1 问题 模型选择问题&#xff1a;对于一个学习问题&#xff0c;可以有多种模型选择。比如要拟合一组样本点&#xff0c;可以使用线性回归&#xff0c;也可以用多项式回归。那么使用哪种模型好呢&#xff08;能够在偏差和方差之间达到平衡最优&#xff09;&#xff1f; 还有一类…

涛神的城堡

涛神的城堡 Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other) Total Submission(s) : 54 Accepted Submission(s) : 13 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description 涛神有一个城堡给游客参观&#…

【51单片机快速入门指南】5.3:SPI控制晶联讯JLX12864G_08602 LCD屏幕

目录示例程序JLX12864G_08602.cJLX12864G_08602.hJLX12864G_08602_Font.cJLX12864G_08602_Font.h测试程序main.c效果STC12LE5A60S2 12MHz Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 示例程序 stdint.h见【51单片机快速入门指南】1&#xff1a;基础知…

Python flask 开发工具和框架安装

https://www.cnblogs.com/Brambling/p/7124286.html

Android二维码之创建

由于微信的推出二维码走进了我们的生活&#xff0c;并且越来越多的人们正在发挥着自己的想象力去使用它&#xff0c;来方便我们的生活&#xff0c;我曾经听说过一个笑话&#xff0c;当我们死后&#xff0c;墓碑上不再有墓志铭&#xff0c;而会出现一个记录你一生信息的二维码&a…

n个台阶,一个人每次最多走m步,算法实现

今天去公司面试做到这个面试题&#xff0c;想了半天还是想到了用递归&#xff0c;回来重新调整一下代码 public class Climb { private int step; public int total; public Climb(int step) { this.step step; } public void climb(int left){ …