java多线程总结

JAVA多线程详解(超详细) 程序:开发写的代码称之为程序。程序就是一堆代码,一组数据和指令集,是一个静态的概念。进程(Process):将程序运行起来,我们称之为进程。进程是执行程序的一次执行过程,它是动态的概念。进程存在生命周期,也就是说程序随着程序的终止而销毁。进程之间是通过TCP/IP端口实现交互的。线程(Thread):线程是进程中的实际运作的单位,是进程的一条流水线,是程序的实际执行者,是最小的执行单位。通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程。线程是CPU调度和执行的最小单位。注意。 阅读详情

java多线程总结

2011-08-28 20:08 by Rollen Holt, 287843 阅读, 82 评论, 收藏, 编辑

以前没有写笔记的习惯,现在慢慢的发现及时总结是多么的重要了,呵呵。虽然才大二,但是也快要毕业了,要加油了。

这一篇文章主要关于java多线程,主要还是以例子来驱动的。因为讲解多线程的书籍和文章已经很多了,所以我也不好意思多说,呵呵、大家可以去参考一些那些书籍。我这个文章主要关于实际的一些问题。同时也算是我以后复习的资料吧,。呵呵大家多多指教。

同时希望多结交一些技术上的朋友。谢谢。

----------------------------------------------------------------------------------------------------------------------------------------------------

                                                                              java中的多线程

在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口。

对于直接继承Thread的类来说,代码大致框架是:

1
2
3
4
5
6
7
8
9
10
11
12
class  类名  extends  Thread{
方法 1 ;
方法 2 ;
…
public  void  run(){
// other code…
}
属性 1 ;
属性 2 ;
…
 
}

先看一个简单的例子:

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
/**
  * @author Rollen-Holt 继承Thread类,直接调用run方法
  * */
class  hello  extends  Thread {
 
     public  hello() {
 
     }
 
     public  hello(String name) {
         this .name = name;
     }
 
     public  void  run() {
         for  ( int  i =  0 ; i <  5 ; i++) {
             System.out.println(name +  "运行     "  + i);
         }
     }
 
     public  static  void  main(String[] args) {
         hello h1= new  hello( "A" );
         hello h2= new  hello( "B" );
         h1.run();
         h2.run();
     }
 
     private  String name;
}

【运行结果】:

A运行     0

A运行     1

A运行     2

A运行     3

A运行     4

B运行     0

B运行     1

B运行     2

B运行     3

B运行     4

我们会发现这些都是顺序执行的,说明我们的调用方法不对,应该调用的是start()方法。

当我们把上面的主函数修改为如下所示的时候:

1
2
3
4
5
6
public  static  void  main(String[] args) {
         hello h1= new  hello( "A" );
         hello h2= new  hello( "B" );
         h1.start();
         h2.start();
     }

然后运行程序,输出的可能的结果如下:

A运行     0

B运行     0

B运行     1

B运行     2

B运行     3

B运行     4

A运行     1

A运行     2

A运行     3

A运行     4

因为需要用到CPU的资源,所以每次的运行结果基本是都不一样的,呵呵。

注意:虽然我们在这里调用的是start()方法,但是实际上调用的还是run()方法的主体。

那么:为什么我们不能直接调用run()方法呢?

我的理解是:线程的运行需要本地操作系统的支持。

如果你查看start的源代码的时候,会发现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public  synchronized  void  start() {
         /**
      * This method is not invoked for the main method thread or "system"
      * group threads created/set up by the VM. Any new functionality added
      * to this method in the future may have to also be added to the VM.
      *
      * A zero status value corresponds to state "NEW".
          */
         if  (threadStatus !=  0  ||  this  != me)
             throw  new  IllegalThreadStateException();
         group.add( this );
         start0();
         if  (stopBeforeStart) {
         stop0(throwableFromStop);
     }
}
private  native  void  start0();

注意我用红色加粗的那一条语句,说明此处调用的是start0()。并且这个这个方法用了native关键字,次关键字表示调用本地操作系统的函数。因为多线程的实现需要本地操作系统的支持。

但是start方法重复调用的话,会出现java.lang.IllegalThreadStateException异常。

通过实现Runnable接口:

 

大致框架是:

1
2
3
4
5
6
7
8
9
10
11
12
class  类名  implements  Runnable{
方法 1 ;
方法 2 ;
…
public  void  run(){
// other code…
}
属性 1 ;
属性 2 ;
…
 
}

 

来先看一个小例子吧:

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
/**
  * @author Rollen-Holt 实现Runnable接口
  * */
class  hello  implements  Runnable {
 
     public  hello() {
 
     }
 
     public  hello(String name) {
         this .name = name;
     }
 
     public  void  run() {
         for  ( int  i =  0 ; i <  5 ; i++) {
             System.out.println(name +  "运行     "  + i);
         }
     }
 
     public  static  void  main(String[] args) {
         hello h1= new  hello( "线程A" );
         Thread demo=  new  Thread(h1);
         hello h2= new  hello( "线程B" );
         Thread demo1= new  Thread(h2);
         demo.start();
         demo1.start();
     }
 
     private  String name;
}

【可能的运行结果】:

线程A运行     0

线程B运行     0

线程B运行     1

线程B运行     2

线程B运行     3

线程B运行     4

线程A运行     1

线程A运行     2

线程A运行     3

线程A运行     4

 

关于选择继承Thread还是实现Runnable接口?

其实Thread也是实现Runnable接口的:

1
2
3
4
5
6
7
8
class  Thread  implements  Runnable {
     //…
public  void  run() {
         if  (target !=  null ) {
              target.run();
         }
         }
}

其实Thread中的run方法调用的是Runnable接口的run方法。不知道大家发现没有,Thread和Runnable都实现了run方法,这种操作模式其实就是代理模式。关于代理模式,我曾经写过一个小例子呵呵,大家有兴趣的话可以看一下:http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144847.html

Thread和Runnable的区别:

如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
  * @author Rollen-Holt 继承Thread类,不能资源共享
  * */
class  hello  extends  Thread {
     public  void  run() {
         for  ( int  i =  0 ; i <  7 ; i++) {
             if  (count >  0 ) {
                 System.out.println( "count= "  + count--);
             }
         }
     }
 
     public  static  void  main(String[] args) {
         hello h1 =  new  hello();
         hello h2 =  new  hello();
         hello h3 =  new  hello();
         h1.start();
         h2.start();
         h3.start();
     }
 
     private  int  count =  5 ;
}

 

【运行结果】:

count= 5

count= 4

count= 3

count= 2

count= 1

count= 5

count= 4

count= 3

count= 2

count= 1

count= 5

count= 4

count= 3

count= 2

count= 1

大家可以想象,如果这个是一个买票系统的话,如果count表示的是车票的数量的话,说明并没有实现资源的共享。

我们换为Runnable接口

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class  MyThread  implements  Runnable{
 
     private  int  ticket =  5 ;   //5张票
 
     public  void  run() {
         for  ( int  i= 0 ; i<= 20 ; i++) {
             if  ( this .ticket >  0 ) {
                 System.out.println(Thread.currentThread().getName()+  "正在卖票" + this .ticket--);
             }
         }
     }
}
public  class  lzwCode {
     
     public  static  void  main(String [] args) {
         MyThread my =  new  MyThread();
         new  Thread(my,  "1号窗口" ).start();
         new  Thread(my,  "2号窗口" ).start();
         new  Thread(my,  "3号窗口" ).start();
     }
}

 

  

 

 

【运行结果】:

count= 5

count= 4

count= 3

count= 2

count= 1

 

总结一下吧:

实现Runnable接口比继承Thread类所具有的优势:

1):适合多个相同的程序代码的线程去处理同一个资源

2):可以避免java中的单继承的限制

3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。

 

所以,本人建议大家劲量实现接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
  * @author Rollen-Holt
  * 取得线程的名称
  * */
class  hello  implements  Runnable {
     public  void  run() {
         for  ( int  i =  0 ; i <  3 ; i++) {
             System.out.println(Thread.currentThread().getName());
         }
     }
 
     public  static  void  main(String[] args) {
         hello he =  new  hello();
         new  Thread(he, "A" ).start();
         new  Thread(he, "B" ).start();
         new  Thread(he).start();
     }
}

【运行结果】:

A

A

A

B

B

B

Thread-0

Thread-0

Thread-0

说明如果我们没有指定名字的话,系统自动提供名字。

提醒一下大家:main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。

 

在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM实习在就是在操作系统中启动了一个进程。

判断线程是否启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
  * @author Rollen-Holt 判断线程是否启动
  * */
class  hello  implements  Runnable {
     public  void  run() {
         for  ( int  i =  0 ; i <  3 ; i++) {
             System.out.println(Thread.currentThread().getName());
         }
     }
 
     public  static  void  main(String[] args) {
         hello he =  new  hello();
         Thread demo =  new  Thread(he);
         System.out.println( "线程启动之前---》"  + demo.isAlive());
         demo.start();
         System.out.println( "线程启动之后---》"  + demo.isAlive());
     }
}

【运行结果】

线程启动之前---》false

线程启动之后---》true

Thread-0

Thread-0

Thread-0

主线程也有可能在子线程结束之前结束。并且子线程不受影响,不会因为主线程的结束而结束。

 

线程的强制执行:

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
/**
      * @author Rollen-Holt 线程的强制执行
      * */
     class  hello  implements  Runnable {
         public  void  run() {
             for  ( int  i =  0 ; i <  3 ; i++) {
                 System.out.println(Thread.currentThread().getName());
             }
         }
     
         public  static  void  main(String[] args) {
             hello he =  new  hello();
             Thread demo =  new  Thread(he, "线程" );
             demo.start();
             for ( int  i= 0 ;i< 50 ;++i){
                 if (i> 10 ){
                     try {
                         demo.join();   //强制执行demo
                     } catch  (Exception e) {
                         e.printStackTrace();
                     }
                 }
                 System.out.println( "main 线程执行-->" +i);
             }
         }
     }

【运行的结果】:

main 线程执行-->0

main 线程执行-->1

main 线程执行-->2

main 线程执行-->3

main 线程执行-->4

main 线程执行-->5

main 线程执行-->6

main 线程执行-->7

main 线程执行-->8

main 线程执行-->9

main 线程执行-->10

线程

线程

线程

main 线程执行-->11

main 线程执行-->12

main 线程执行-->13

...

 

线程的休眠:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
  * @author Rollen-Holt 线程的休眠
  * */
class  hello  implements  Runnable {
     public  void  run() {
         for  ( int  i =  0 ; i <  3 ; i++) {
             try  {
                 Thread.sleep( 2000 );
             }  catch  (Exception e) {
                 e.printStackTrace();
             }
             System.out.println(Thread.currentThread().getName() + i);
         }
     }
 
     public  static  void  main(String[] args) {
         hello he =  new  hello();
         Thread demo =  new  Thread(he,  "线程" );
         demo.start();
     }
}

【运行结果】:(结果每隔2s输出一个)

线程0

线程1

线程2

 

线程的中断:

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
/**
  * @author Rollen-Holt 线程的中断
  * */
class  hello  implements  Runnable {
     public  void  run() {
         System.out.println( "执行run方法" );
         try  {
             Thread.sleep( 10000 );
             System.out.println( "线程完成休眠" );
         }  catch  (Exception e) {
             System.out.println( "休眠被打断" );
             return ;   //返回到程序的调用处
         }
         System.out.println( "线程正常终止" );
     }
 
     public  static  void  main(String[] args) {
         hello he =  new  hello();
         Thread demo =  new  Thread(he,  "线程" );
         demo.start();
         try {
             Thread.sleep( 2000 );
         } catch  (Exception e) {
             e.printStackTrace();
         }
         demo.interrupt();  //2s后中断线程
     }
}

【运行结果】:

执行run方法

休眠被打断

 

在java程序中,只要前台有一个线程在运行,整个java程序进程不会小时,所以此时可以设置一个后台线程,这样即使java进程小时了,此后台线程依然能够继续运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
  * @author Rollen-Holt 后台线程
  * */
class  hello  implements  Runnable {
     public  void  run() {
         while  ( true ) {
             System.out.println(Thread.currentThread().getName() +  "在运行" );
         }
     }
 
     public  static  void  main(String[] args) {
         hello he =  new  hello();
         Thread demo =  new  Thread(he,  "线程" );
         demo.setDaemon( true );
         demo.start();
     }
}

虽然有一个死循环,但是程序还是可以执行完的。因为在死循环中的线程操作已经设置为后台运行了。

线程的优先级:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
  * @author Rollen-Holt 线程的优先级
  * */
class  hello  implements  Runnable {
     public  void  run() {
         for ( int  i= 0 ;i< 5 ;++i){
             System.out.println(Thread.currentThread().getName()+ "运行" +i);
         }
     }
 
     public  static  void  main(String[] args) {
         Thread h1= new  Thread( new  hello(), "A" );
         Thread h2= new  Thread( new  hello(), "B" );
         Thread h3= new  Thread( new  hello(), "C" );
         h1.setPriority( 8 );
         h2.setPriority( 2 );
         h3.setPriority( 6 );
         h1.start();
         h2.start();
         h3.start();
         
     }
}

 

【运行结果】:

A运行0

A运行1

A运行2

A运行3

A运行4

B运行0

C运行0

C运行1

C运行2

C运行3

C运行4

B运行1

B运行2

B运行3

B运行4

。但是请读者不要误以为优先级越高就先执行。谁先执行还是取决于谁先去的CPU的资源、

 

另外,主线程的优先级是5.

线程的礼让。

在线程操作中,也可以使用yield()方法,将一个线程的操作暂时交给其他线程执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
  * @author Rollen-Holt 线程的优先级
  * */
class  hello  implements  Runnable {
     public  void  run() {
         for ( int  i= 0 ;i< 5 ;++i){
             System.out.println(Thread.currentThread().getName()+ "运行" +i);
             if (i== 3 ){
                 System.out.println( "线程的礼让" );
                 Thread.currentThread().yield();
             }
         }
     }
 
     public  static  void  main(String[] args) {
         Thread h1= new  Thread( new  hello(), "A" );
         Thread h2= new  Thread( new  hello(), "B" );
         h1.start();
         h2.start();
         
     }
}

A运行0

A运行1

A运行2

A运行3

线程的礼让

A运行4

B运行0

B运行1

B运行2

B运行3

线程的礼让

B运行4

 

 

同步和死锁:

【问题引出】:比如说对于买票系统,有下面的代码:

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
/**
  * @author Rollen-Holt
  * */
class  hello  implements  Runnable {
     public  void  run() {
         for ( int  i= 0 ;i< 10 ;++i){
             if (count> 0 ){
                 try {
                     Thread.sleep( 1000 );
                 } catch (InterruptedException e){
                     e.printStackTrace();
                 }
                 System.out.println(count--);
             }
         }
     }
 
     public  static  void  main(String[] args) {
         hello he= new  hello();
         Thread h1= new  Thread(he);
         Thread h2= new  Thread(he);
         Thread h3= new  Thread(he);
         h1.start();
         h2.start();
         h3.start();
     }
     private  int  count= 5 ;
}

【运行结果】:

5

4

3

2

1

0

-1

这里出现了-1,显然这个是错的。,应该票数不能为负值。

如果想解决这种问题,就需要使用同步。所谓同步就是在统一时间段中只有有一个线程运行,

其他的线程必须等到这个线程结束之后才能继续执行。

【使用线程同步解决问题】

采用同步的话,可以使用同步代码块和同步方法两种来完成。

 

【同步代码块】:

语法格式:

synchronized(同步对象){

 //需要同步的代码

}

但是一般都把当前对象this作为同步对象。

比如对于上面的买票的问题,如下:

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
/**
  * @author Rollen-Holt
  * */
class  hello  implements  Runnable {
     public  void  run() {
         for ( int  i= 0 ;i< 10 ;++i){
             synchronized  ( this ) {
                 if (count> 0 ){
                     try {
                         Thread.sleep( 1000 );
                     } catch (InterruptedException e){
                         e.printStackTrace();
                     }
                     System.out.println(count--);
                 }
             }
         }
     }
 
     public  static  void  main(String[] args) {
         hello he= new  hello();
         Thread h1= new  Thread(he);
         Thread h2= new  Thread(he);
         Thread h3= new  Thread(he);
         h1.start();
         h2.start();
         h3.start();
     }
     private  int  count= 5 ;
}

【运行结果】:(每一秒输出一个结果)

5

4

3

2

1

【同步方法】

也可以采用同步方法。

语法格式为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
29
30
31
32
33
/**
  * @author Rollen-Holt
  * */
class  hello  implements  Runnable {
     public  void  run() {
         for  ( int  i =  0 ; i <  10 ; ++i) {
             sale();
         }
     }
 
     public  synchronized  void  sale() {
         if  (count >  0 ) {
             try  {
                 Thread.sleep( 1000 );
             }  catch  (InterruptedException e) {
                 e.printStackTrace();
             }
             System.out.println(count--);
         }
     }
 
     public  static  void  main(String[] args) {
         hello he =  new  hello();
         Thread h1 =  new  Thread(he);
         Thread h2 =  new  Thread(he);
         Thread h3 =  new  Thread(he);
         h1.start();
         h2.start();
         h3.start();
     }
 
     private  int  count =  5 ;
}

【运行结果】(每秒输出一个)

5

4

3

2

1

提醒一下,当多个线程共享一个资源的时候需要进行同步,但是过多的同步可能导致死锁。

此处列举经典的生产者和消费者问题。

【生产者和消费者问题】

先看一段有问题的代码。

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
class  Info {
 
     public  String getName() {
         return  name;
     }
 
     public  void  setName(String name) {
         this .name = name;
     }
 
     public  int  getAge() {
         return  age;
     }
 
     public  void  setAge( int  age) {
         this .age = age;
     }
 
     private  String name =  "Rollen" ;
     private  int  age =  20 ;
}
 
/**
  * 生产者
  * */
class  Producer  implements  Runnable{
     private  Info info= null ;
     Producer(Info info){
         this .info=info;
     }
     
     public  void  run(){
         boolean  flag= false ;
         for ( int  i= 0 ;i< 25 ;++i){
             if (flag){
                 this .info.setName( "Rollen" );
                 try {
                     Thread.sleep( 100 );
                 } catch  (Exception e) {
                     e.printStackTrace();
                 }
                 this .info.setAge( 20 );
                 flag= false ;
             } else {
                 this .info.setName( "chunGe" );
                 try {
                     Thread.sleep( 100 );
                 } catch  (Exception e) {
                     e.printStackTrace();
                 }
                 this .info.setAge( 100 );
                 flag= true ;
             }
         }
     }
}
/**
  * 消费者类
  * */
class  Consumer  implements  Runnable{
     private  Info info= null ;
     public  Consumer(Info info){
         this .info=info;
     }
     
     public  void  run(){
         for ( int  i= 0 ;i< 25 ;++i){
             try {
                 Thread.sleep( 100 );
             } catch  (Exception e) {
                 e.printStackTrace();
             }
             System.out.println( this .info.getName()+ "<---->" + this .info.getAge());
         }
     }
}
 
/**
  * 测试类
  * */
class  hello{
     public  static  void  main(String[] args) {
         Info info= new  Info();
         Producer pro= new  Producer(info);
         Consumer con= new  Consumer(info);
         new  Thread(pro).start();
         new  Thread(con).start();
     }
}

【运行结果】:

Rollen<---->100

chunGe<---->20

chunGe<---->100

Rollen<---->100

chunGe<---->20

Rollen<---->100

Rollen<---->100

Rollen<---->100

chunGe<---->20

chunGe<---->20

chunGe<---->20

Rollen<---->100

chunGe<---->20

Rollen<---->100

chunGe<---->20

Rollen<---->100

chunGe<---->20

Rollen<---->100

chunGe<---->20

Rollen<---->100

chunGe<---->20

Rollen<---->100

chunGe<---->20

Rollen<---->100

chunGe<---->20

大家可以从结果中看到,名字和年龄并没有对于。

 

那么如何解决呢?

1)加入同步

2)加入等待和唤醒

先来看看加入同步会是如何。

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
class  Info {
     
     public  String getName() {
         return  name;
     }
 
     public  void  setName(String name) {
         this .name = name;
     }
 
     public  int  getAge() {
         return  age;
     }
 
     public  void  setAge( int  age) {
         this .age = age;
     }
 
     public  synchronized  void  set(String name,  int  age){
         this .name=name;
         try {
             Thread.sleep( 100 );
         } catch  (Exception e) {
             e.printStackTrace();
         }
         this .age=age;
     }
     
     public  synchronized  void  get(){
         try {
             Thread.sleep( 100 );
         } catch  (Exception e) {
             e.printStackTrace();
         }
         System.out.println( this .getName()+ "<===>" + this .getAge());
     }
     private  String name =  "Rollen" ;
     private  int  age =  20 ;
}
 
/**
  * 生产者
  * */
class  Producer  implements  Runnable {
     private  Info info =  null ;
 
     Producer(Info info) {
         this .info = info;
     }
 
     public  void  run() {
         boolean  flag =  false ;
         for  ( int  i =  0 ; i <  25 ; ++i) {
             if  (flag) {
                 
                 this .info.set( "Rollen" ,  20 );
                 flag =  false ;
             }  else  {
                 this .info.set( "ChunGe" ,  100 );
                 flag =  true ;
             }
         }
     }
}
 
/**
  * 消费者类
  * */
class  Consumer  implements  Runnable {
     private  Info info =  null ;
 
     public  Consumer(Info info) {
         this .info = info;
     }
 
     public  void  run() {
         for  ( int  i =  0 ; i <  25 ; ++i) {
             try  {
                 Thread.sleep( 100 );
             }  catch  (Exception e) {
                 e.printStackTrace();
             }
             this .info.get();
         }
     }
}
 
/**
  * 测试类
  * */
class  hello {
     public  static  void  main(String[] args) {
         Info info =  new  Info();
         Producer pro =  new  Producer(info);
         Consumer con =  new  Consumer(info);
         new  Thread(pro).start();
         new  Thread(con).start();
     }
}

【运行结果】:

Rollen<===>20

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

Rollen<===>20

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

ChunGe<===>100

从运行结果来看,错乱的问题解决了,现在是Rollen 对应20,ChunGe对于100

,但是还是出现了重复读取的问题,也肯定有重复覆盖的问题。如果想解决这个问题,就需要使用Object类帮忙了、

,我们可以使用其中的等待和唤醒操作。

要完成上面的功能,我们只需要修改Info类饥渴,在其中加上标志位,并且通过判断标志位完成等待和唤醒的操作,代码如下:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
class  Info {
     
     public  String getName() {
         return  name;
     }
 
     public  void  setName(String name) {
         this .name = name;
     }
 
     public  int  getAge() {
         return  age;
     }
 
     public  void  setAge( int  age) {
         this .age = age;
     }
 
     public  synchronized  void  set(String name,  int  age){
         if (!flag){
             try {
                 super .wait();
             } catch  (Exception e) {
                 e.printStackTrace();
             }
         }
         this .name=name;
         try {
             Thread.sleep( 100 );
         } catch  (Exception e) {
             e.printStackTrace();
         }
         this .age=age;
         flag= false ;
         super .notify();
     }
     
     public  synchronized  void  get(){
         if (flag){
             try {
                 super .wait();
             } catch  (Exception e) {
                 e.printStackTrace();
             }
         }
         
         try {
             Thread.sleep( 100 );
         } catch  (Exception e) {
             e.printStackTrace();
         }
         System.out.println( this .getName()+ "<===>" + this .getAge());
         flag= true ;
         super .notify();
     }
     private  String name =  "Rollen" ;
     private  int  age =  20 ;
     private  boolean  flag= false ;
}
 
/**
  * 生产者
  * */
class  Producer  implements  Runnable {
     private  Info info =  null ;
 
     Producer(Info info) {
         this .info = info;
     }
 
     public  void  run() {
         boolean  flag =  false ;
         for  ( int  i =  0 ; i <  25 ; ++i) {
             if  (flag) {
                 
                 this .info.set( "Rollen" ,  20 );
                 flag =  false ;
             }  else  {
                 this .info.set( "ChunGe" ,  100 );
                 flag =  true ;
             }
         }
     }
}
 
/**
  * 消费者类
  * */
class  Consumer  implements  Runnable {
     private  Info info =  null ;
 
     public  Consumer(Info info) {
         this .info = info;
     }
 
     public  void  run() {
         for  ( int  i =  0 ; i <  25 ; ++i) {
             try  {
                 Thread.sleep( 100 );
             }  catch  (Exception e) {
                 e.printStackTrace();
             }
             this .info.get();
         }
     }
}
 
/**
  * 测试类
  * */
class  hello {
     public  static  void  main(String[] args) {
         Info info =  new  Info();
         Producer pro =  new  Producer(info);
         Consumer con =  new  Consumer(info);
         new  Thread(pro).start();
         new  Thread(con).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
【程序运行结果】:
Rollen<===> 20
ChunGe<===> 100
Rollen<===> 20
ChunGe<===> 100
Rollen<===> 20
ChunGe<===> 100
Rollen<===> 20
ChunGe<===> 100
Rollen<===> 20
ChunGe<===> 100
Rollen<===> 20
ChunGe<===> 100
Rollen<===> 20
ChunGe<===> 100
Rollen<===> 20
ChunGe<===> 100
Rollen<===> 20
ChunGe<===> 100
Rollen<===> 20
ChunGe<===> 100
Rollen<===> 20
ChunGe<===> 100
Rollen<===> 20
ChunGe<===> 100
Rollen<===> 20
先在看结果就可以知道,之前的问题完全解决。

《完》

PS(写在后面):

本人深知学的太差,所以希望大家能多多指点。另外,关于多线程其实有很多的知识,由于目前我也就知道的不太多,写了一些常用的。虽然在操作系统这门课上学了很多的线程和进程,比如银行家算法等等的,以后有时间在补充,大家有什么好资料可以留个言,大家一起分享一下,谢谢了。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


============================================================================== 
我喜欢程序员,他们单纯、固执、容易体会到成就感;面对压力,能够挑灯夜战不眠不休;面对困难,能够迎难而上挑战自我。他
们也会感到困惑与傍徨,但每个程序员的心中都有一个比尔盖茨或是乔布斯的梦想“用智慧开创属于自己的事业”。我想说的是,其
实我是一个程序员

==============================================================================
70
0
(请您对文章做出评价)
« 上一篇: 棋盘覆盖--递归分治java实现
» 下一篇: java中类的生命周期
< Prev 1 2
ADD YOUR COMMENT
  1. #51楼 白开水加糖  2013-09-28 21:25
    @yyg1982
    会不会是单核CPU执行的时候不行? 我觉得楼主写的么错啊
  2. #52楼 shuyy_com  2013-10-28 13:26
    写得很好,谢谢,辛苦了
  3. #53楼 沙漠中的大奔  2013-11-02 22:07
    楼主 为什么不学java了呢?
  4. #54楼[楼主] Rollen Holt  2013-11-04 10:26
    @沙漠中的大奔
    工作的关系,哈哈
  5. #55楼 你的名字我的姓氏  2013-11-28 16:21
    不错,讲的很细
  6. #56楼 道上的追逐  2013-12-26 09:36
    不错很详细,适合我们这些新手
  7. #57楼 会呼吸的鱼  2013-12-27 11:40
    很好,lz辛苦了
  8. #58楼 fkblog.org  2014-01-13 09:50
    不错,我也推荐个Java多线程入门讲解: http://www.w3cschool.cc/java/ava-multithreading.html
  9. #59楼 reiben  2014-01-28 16:41
    public class lzwCode {
         
        public static void main(String [] args) {
            MyThread my = new MyThread();
            new Thread(my, "1号窗口").start();
            new Thread(my, "2号窗口").start();
            new Thread(my, "3号窗口").start();
        }
    }

    这个分配了3个线程对象,但运行的都是同一个线程MyThread,内存中就一份COUNT=5.

    class hello extends Thread {
    public void run() {
    for (int i = 0; i < 7; i++) {
    if (count > 0) {
    System.out.println("count= " + count--);
    }
    }
    }

    public static void main(String[] args) {
    hello h1 = new hello();
    hello h2 = new hello();
    hello h3 = new hello();
    h1.start();
    h2.start();
    h3.start();
    }

    private int count = 5;
    }

    这个新建了3个线程,内存中有三份COUNT=5.

    跑出来的结果自然不一样了。是可以共享的。
  10. #60楼 reiben  2014-01-28 16:43
    class hello extends Thread {
    public void run() {
    for (int i = 0; i < 7; i++) {
    if (count > 0) {
    System.out.println("count= " + count--);
    }
    }
    }

    public static void main(String[] args) {
    hello h1 = new hello();
    hello h2 = new hello();
    hello h3 = new hello();
    h1.start();
    h2.start();
    h3.start();
    }

    private int count = 5;
    }

    把
    private int count = 5;
    改成
    private static int count = 5;试试
  11. #61楼 Vitt不再孤单  2014-01-30 00:14
    每次看到你们这样的笔记就会想,当初自己不学测控多好····妈蛋····
  12. #62楼 BIGBIRD大鸟  2014-02-10 22:41
    写的真好! 很详细了!
  13. #63楼 无翼神  2014-02-13 20:03
    写的不错,例子也不错
  14. #64楼 simpman  2014-02-27 15:48
    大家可以想象,如果这个是一个买票系统的话,如果count表示的是车票的数量的话,说明并没有实现资源的共享。
    我们换为Runnable接口

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    class MyThread implements Runnable{

    private int ticket = 5; //5张票

    public void run() {
    for (int i=0; i<=20; i++) {
    if (this.ticket > 0) {
    System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--);
    }
    }
    }
    }
    public class lzwCode {

    public static void main(String [] args) {
    MyThread my = new MyThread();
    new Thread(my, "1号窗口").start();
    new Thread(my, "2号窗口").start();
    new Thread(my, "3号窗口").start();
    }
    }

    这个也会出现两个窗口卖同一张票的情况。应该用synchronized给代码加锁吧。
  15. #65楼 Bactryki  2014-04-18 11:29
    真棒!
  16. #66楼 beyondchina  2014-04-21 13:46
    mark. 写得很不错哦。
  17. #67楼 小咚  2014-04-22 17:24
    public synchronized void set(String name, int age){
    if(!flag){
    try{
    super.wait();
    }catch (Exception e) {
    e.printStackTrace();
    }
    }
    this.name=name;
    try{
    Thread.sleep(100);
    }catch (Exception e) {
    e.printStackTrace();
    }
    this.age=age;
    flag=false;
    super.notify();
    }

    public synchronized void get(){
    if(flag){
    try{
    super.wait();
    }catch (Exception e) {
    e.printStackTrace();
    }
    }

    try{
    Thread.sleep(100);
    }catch (Exception e) {
    e.printStackTrace();
    }
    System.out.println(this.getName()+"<===>"+this.getAge());
    flag=true;
    super.notify();
    }
    private String name = "Rollen";
    private int age = 20;
    private boolean flag=false;
    }

    这个生产者和消费者的判断应该反了把
    生产应该是set 应该是!flag 没有就创建 然后激活get 有就等待消费
    消费应该是get 应该是flag 有就消费 然后激活set 没有就等待生产
  18. #68楼 拉姆塞  2014-04-23 09:14
    学习了,谢谢
  19. #69楼 youngjoy  2014-05-17 00:15
    写的太好。学习。膜拜。
  20. #70楼 水澜。影雪  2014-05-19 10:30
    很好,非常适合我们新手~
  21. #71楼 xmu_lomo  2014-05-21 08:44
    楼主在线程的强制执行那段是怎么样得到那样的结果的...我的至少得在run中执行5次及5次以上才可能在main线程10以后join, 0-0楼主的输出结果概率略小呀,...
  22. #72楼 Me.thinking  2014-05-21 16:12
    good
  23. #73楼 秦寅  2014-05-29 17:39
    楼主在说明多线程两种实现方式资源共享的时候,demo卖票是错误的。
    class hello extends Thread {
    public void run() {
    for (int i = 0; i < 7; i++) {
    if (count > 0) {
    System.out.println("count= " + count--);
    }
    }
    }

    public static void main(String[] args) {
    hello h1 = new hello();
    hello h2 = new hello();
    hello h3 = new hello();
    h1.start();
    h2.start();
    h3.start();
    }

    private int count = 5;
    }
    这个继承Thread实现的方法,在main方法中其实是创建了是三个线程,所以运行的时候输出的是15条记录。但是如下实例:

    private int ticket = 5; //5张票

    public void run() {
    for (int i=0; i<=20; i++) {
    if (this.ticket > 0) {
    System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--);
    }
    }
    }
    }
    public class lzwCode {

    public static void main(String [] args) {
    MyThread my = new MyThread();
    new Thread(my, "1号窗口").start();
    new Thread(my, "2号窗口").start();
    new Thread(my, "3号窗口").start();
    }
    }
    这个是通过实现Runnable接口实现资源共享中,只是创建了一个线程。在如下是我自己写的实例,同样可以实现资源共享的目的:
    public class Hello extends Thread{

    public Hello() {

    }

    public Hello(String name) {
    this.name = name;
    }

    private int ticket=10;
    public void run() {
    for (int i = 0; i < 5; i++) {
    if(ticket>0){
    System.out.println(Thread.currentThread().getName()+ "--" +this.ticket--);
    }
    }
    }

    public static void main(String[] args) {
    Hello h3 = new Hello();
    new Thread(h3, "窗口1").start();
    new Thread(h3, "窗口2").start();
    new Thread(h3, "窗口3").start();
    }

    private String name;

    }
  24. #74楼 oddsworld  2014-07-24 15:51
    此篇文章有多处错误,比如说到Thread,和Runnable的区别说的资源共享,“实现Runnable接口比继承Thread类所具有的优势:

    1):适合多个相同的程序代码的线程去处理同一个资源” 文中没有使用静态变量,没有资源共享的提现,
    另有一处说到 join用法, 说到“ demo.join(); //强制执行demo”也是错误的,join是等待该 demo线程结束才跳转另外线程。
    暂时看到这些,不过文章总体还是有借鉴价值。
  25. #75楼 huamaoenjoy  2014-08-07 15:49
    你这个代码怎么插入的?格式很好看呀?求教一下
  26. #76楼[楼主] Rollen Holt  2014-08-07 18:54
    @huamaoenjoy
    博客园自带的代码高亮啊。另外推荐使用博客园最近支持的Markdown。格式个人感觉更好看
  27. #77楼 WilsonPeng  2014-09-02 10:11
    本文有些地方真不敢苟同。好多错误,确实不想往下看了。1:楼主观点说Runnable接口方便共享资源。这里不能说错,但举的例子实在是错误。2:楼主观点:主线程结束,子线程可能不会结束。先暂不说这个是对是错,但举的例子实在不能说明论证这个观点。还有处代码的注释:demo.join() //强制执行demo ,看到这个注释,实在不想继续往下看了。
  28. #78楼 WilsonPeng  2014-09-02 10:15
    希望楼主要么把博文修改下,要么删了。不做任何处理的话,真有点误导。言辞有点不当,但是实话。
  29. #79楼[楼主] Rollen Holt  2014-09-02 10:35
    @WilsonPeng
    本文章已经不维护.原文如果有错,我也懒得改了,也懒的删.
  30. #80楼 快鸟  2014-11-20 16:06
    之所以不使用run()来调度线程,是因为调用run()只是简单的方法调用,而不是重新启动一个线程。

    synchronized(this){......}是不能达到同步效果的,除非在单例模式下。
    简单的在方法前面加synchronized也不能达到预期的同步效果。

    这两种都是由于线程持有各自的同步锁,而不能达到同步效果。

    要实现预期的同步效果,必须保证所有线程的同步锁共享且唯一。
  31. #81楼 泡沫__opt  2014-11-30 17:16
    好长啊……但真详细~~
  32. #82楼 红桃J  2014-12-05 19:49
    谢谢楼主!从你这儿学习了!
< Prev 1 2
SOC估算方法之(OCV-SOC+安时积分法) 此方法主要参考。 阅读详情

相关推荐

泛微E8流程监控指南:如何用SQL实时追踪审批节点状态?

本文详细介绍了如何利用SQL实时监控泛微E8系统中的审批流程状态,包括核心数据表结构解析、全链路监控SQL实战以及智能预警机制设计。通过数据库直接查询和状态关联分析,帮助企业快速定位卡顿节点,提升流程效率。适用于需要优化OA系统流程管理的企业IT人员和业务主管。

weixin_30687051的博客 440

Java多线程知识点,看这一篇就够了!(超详细)

1、饿汉模式(迫切)程序启动,类加载之后,立即创建出实例2、懒汉模式(延时)在第一次使用实例的时候,再创建,否则能不创建就不创建举个例子:编译器打开一个文件,假设有一个超大的文件,

weixin_73616913的博客 5491

SAP PP后台配置实战:从BOM到工艺路线的全流程解析

本文详细解析了SAP PP模块后台配置的全流程,从BOM到工艺路线的关键步骤与实战技巧。通过分享生产计划、工作中心能力计划等核心配置经验,帮助企业优化生产管理流程,提升SAP系统实施效率。特别针对BOM配置、工艺路线设置等常见问题提供解决方案。

weixin_29300931的博客 1010

Java多线程超详细总结

多线程概述 多线程是Java的特点之一,掌握多线程编程技术,可以充分利用CPU的资源,更容易解决实际问题,并且多线程技术广泛应用于网络相关的程序设计中。 进程 进程是程序的一次动态执行过程,它对应了从代码加载、执行至完毕的一个完整过程,这个过程也是进程本身从产、发展至消亡的过程。 线程 线程是比进程更小的执行单位,一个进程在其执行过程中,可以产生多个线程,形成多条执行线索,每条线索,即每个线程,也有它自身产生、存在和消亡的过程。与进程可以共享操作系统的资源类似,线程间也可以共享进程中的某些内存单元(包括代码

star_zhang_jx的博客 1405

大模型-internvl高通qnn运行源码解读

模型链接:https://huggingface.co/OpenGVLab/InternVL2-2B论文官方简要说明 https://internvl.github.io/blog/2024-07-02-InternVL-2.0中文解读 https://zhuanlan.zhihu.com/p/702946079在线demo https://internvl.opengvlab.com/

点滴的岁月 1833

RTKLIB中RTK定位原理(一)

1 模型 1.1 非差观测值 非差观测值与RTKLIB中PPP定位原理——观测模型部分中一致。 1.2 单间单差观测值 若两个接收机距离较近,经过站间单差,电离层对流层延迟可消除,卫星s的钟差以及初始相位被消除,中依然包含接收机初始相位。 1.3 站间星间双差观测值 经过站间星间双差,接收机钟差及初始相位被消除。 2 EKF参数估计 2.1 EKF法则 EKF法则与RTKLIB中PPP定位原理——观测模型部分中一致。 2.2 状态变量与时间更新 (1)状态变量 在RTK...

papunzal的博客 3819

Java多线程 基础知识的总结

多线程的基础

m0_62567916的博客 401

YOLOv13改进:原创自研 | 卷积魔改 | 一种新颖的风车形卷积(PConv)融合注意力机制,加强微弱小目标检测能力

风车形卷积(PConv)融合注意力机制进一步提升小目标检测能力

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 1058

Java的多线程

一、线程简介 1.什么是进程: 进程是程序的运行过程,是系统进行资源分配和调度的一个独立单位。通俗来讲,进程就是在操作系统中运行的程序,例如:电脑中运行的微信、eclipse、idea等。 2.什么是线程 线程是操作系统能够进行运算调度的最小单位。一个进程至少有一个线程,一个程序可以有多个线程。 3.多线程 如果一个程序可以同时运行多个线程,那么这个程序就是多线程的。例如看视频时程序同时进行加载图像、获取字幕和获取弹幕等。 二、线程的创建 1.继承Thread类 步骤: (1)创建线程类,并继承Thread

锟斤拷 320

matplotlib保存图片设置分辨率总是96dpi,好烦躁,教你一招轻松解决

matplotlib保存图片设置分辨率总是96dpi,好烦躁,教你一招轻松解决 目录 matplotlib保存图片设置分辨率总是96dpi,好烦躁,教你一招轻松解决 #使用plt.savefig("cm.png",dpi = 300)为什么不管用 #plt.rcParams也不管用 #解决方案 在做论文的过程中,许多期刊或者会议对图片的分辨率有明确的要求,例如,dpi=300。 之前画曲线图都是采取保存方式为savefig(dpi=300),然后查看保存图片的属性信息,然而你看到的现象是

data+scenario+science+insight 8800

Windows 下 OpenClaw(小龙虾) 安装全记录:从零到一的保姆级图文教程(持续更新中)

本文主要介绍了Windows 下 OpenClaw 安装全记录:从零到一的保姆级图文教程,希望能对学习使用OpenClaw 的同学们有所帮助。 文章目录 1. 背景 2. 实战教程 2.1 步骤一 安装Node.js 2.2 步骤二:安装并配置OpenClaw 2.3 步骤三:配置模型 2.4 步骤四:对话 3. 后续使用步骤

weixin_43178406的博客 16万+

Java多线程详解(一)Java多线程入门

最近听很多面试的小伙伴说,网上往往是一篇一篇的Java多线程的文章,除了书籍没有什么学习多线程的一系列文章。但是仅仅凭借一两篇文章很难对多线程有系统的学习,而且面试的时候多线程这方面的知识往往也是考察的重点,所以考虑之下决定写一系列关于Java多线程的文章。文章参考了高老师的《Java多线程编程核心技术》。力争使用最短的篇幅把Java多线程的知识作以系统的讲述。 本节思维导图: 思维导图...

刘成 2475

YOLO26涨点改进 | Conv篇/小目标改进 | AAAI 2025 FBRT-YOLO 两个轻量级FCM和MKP模块, 助力无人机航拍任务VisDrone、UAVDT和AI-TOD高效涨点

本文提出FBRT-YOLO26模型,通过引入两个轻量级模块FCM和MKP优化航拍图像检测性能。FCM模块通过特征互补映射解决小目标信息丢失问题,MKP模块利用多尺度卷积核增强目标感知能力。在VisDrone等数据集上的实验表明,该方法在精度和速度上均优于现有实时检测器。文章详细介绍了模块结构、核心代码实现及YAML配置文件修改方法,为航拍图像中的小目标检测提供了高效解决方案。该模型实现了检测精度与效率的良好平衡,具有实际应用价值。

Ai缝合怪、助力小伙伴高效发论文 369

Java技术——Java多线程学习

0.前言 转载请标明出处:http://blog.youkuaiyun.com/seu_calvin/article/details/52400927 学习多线程之前需要先了解以下几个概念。 进程:一般指一个程序运行时的实例,每个进程有自己独立的地址空间。一个进程无法直接访问另一个进程的数据。 线程:是CPU调度的最小单元,一个进程可以有很多线程,每条线程可以并行执行不同的任务。并且每个线程有独立的运...

关于Android开发的一些技术点总结 ╮( ̄▽ ̄”)╭ 1万+

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java 多线程详解

多线程(Multithreading)是指在一个程序中同时执行多个线程的能力。线程是进程中的一个执行路径,多线程允许程序在同一时间内执行多个操作。Java 中的多线程可以通过并发处理来提高程序的性能和响应速度,尤其在处理复杂计算、大量 I/O 操作或并发任务时非常有用。多线程使得程序可以同时执行多个任务,充分利用CPU资源,提升程序性能,增强响应性,并简化程序的复杂度。尽管多线程编程带来了一些挑战,如线程安全和死锁问题,但合理设计和使用多线程可以显著改善程序的整体表现。

goTsHgo的博客 2040

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【Java多线程】Java多线程技能

到 1. 进程和多线程的概念及线程的优点 提到多线程这个技术就不得不提及“进程”这个概念,在“百度百科”中对进程的解释如下: 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。 进程是受操作系统管理的基本运行单元。 那什么是线程呢? 线程可以理解成是在

一定要站在自己热爱的生活里闪闪发光 4万+

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

java多线程

在计算机中,我们把一个任务称为一个进程,浏览器就是一个进程,视频播放器是另一个进程,类似的,音乐播放器和Word都是进程。某些进程内部还需要同时执行多个子任务。例如,我们在使用Word时,Word可以让我们一边打字,一边进行拼写检查,同时还可以在后台进行打印,我们把子任务称为线程。进程和线程的关系就是:一个进程可以包含一个或多个线程,但至少会有一个线程。操作系统调度的最小任务单位其实不是进程,而是线程。

m0_60301012的博客 775

JAVA多线程是什么

一、 什么是多线程: 我们现在所使用操作系统都是多任务操作系统(早期使用的DOS操作系统为单任务操作系统),多任务操作指在同一时刻可以同时做多件事(可以同时执行多个程序)。 多进程:每个程序都是一个进程,在操作系统中可以同时执行多个程序,多进程的目的是为了有效的使用CPU资源,每开一个进程系统要为该进程分配相关的系统资源(内存资源) 多线程:线程是进程内部比进程更小的执行单元(执行流|程序片段),每个线程完成一个任务,每个进程内部包含了多个线程每个线程做自己的事情,在进程中的所有线程共享该进程的资源; 主

qq_45022104的博客 4446

Java多线程详解

线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

坏蛋阿土的博客 6820

Java多线程

死锁就是两个线程相互等待对方释放对象锁。很简单,简单看名字就知道是装有线程的池子,我们可以把要执行的多线程交给线程池来处理,和连接池的概念一样,通过维护一定数量的线程池来达到多个线程的复用。

vip_member888的博客 1164

java多线程是什么_Java多线程是什么

本篇文章将介绍一下多线程和其实例。Java编写程序都运行在在Java虚拟机(JVM)中,在JVM的内部,程序的多任务是通过线程来实现的。每用java命令启动一个java应用程 序,就会启动一个JVM进程。在同一个JVM进程中,有且只有一个进程,就是它自己。在这个JVM环境中,所有程序代码的运行都是以线 程来运行。一般常见的Java应用程序都是单线程的。比如,用java命令运行一个最简单的Hello...

weixin_33050129的博客 379

java多线程应用_Java多线程的应用总结

多线程的好处:在java中通常每一个任务称为一个线程,但是多线程实现一个程序同时执行多个任务。直接了当的说多线程可以把任务分块执行,分块后可以同时进行而不用等待。 如下载文件,浏览网站时加载图片,通过多线程就可以实现多文件下载,一下做好几个工作,这样效率更高,线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实...

weixin_31081671的博客 774

java多线程 cpu分配_java多线程总结(转载)

Java 多线程编程总结-------------------------------------------------------------------------------------------------下面的内容是很早之前写的,内容不够充实,而且是基于Java1.4的内容,Java5之后,线程并发部分扩展了相当多的内容,因此建议大家看 上面的系列文章的内容,与时俱进,跟上Java发...

weixin_39588983的博客 1604

Java-多线程_java 多线程

Java多线程编程是提升程序性能的核心技术,通过并发执行任务提高CPU和I/O资源利用率。文章详细介绍了四种线程创建方式:继承Thread类、实现Runnable接口、使用Callable返回结果,以及更高效的线程池管理。重点讲解了线程的六种状态转换和关键的同步机制,包括synchronized关键字和Lock接口的使用,确保线程安全。通过计数器示例演示了如何避免数据竞争,为开发者提供了一套完整的Java多线程编程解决方案。

m0_57545130的博客 836
上一篇: android AsyncTask介绍
下一篇: 线程安全与可重入
codepython
博客等级 码龄20年 125粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值