进程有自己独立的内存空间,线程之间是共享内存的
使用Thread来实现多线程,弊端比较多,不建议使用。
Runnable接口(最常用的实现多线程的接口,建议使用)
Runnable 接口 相对于 继承Thread类来说,有以下优点:
1, 适合多个相同程序的代码(同一段代码,开辟N个线程)去处理同一个资源(比如联网售票,票的个数是共同的)的情况。// 把线程(售票点),实现代码(卖票)和数据(票)有效的分离开,较好的实现了面向对象的设计思想。
2, 可以避免由于java的单继承特性所带来的局限性。比如:一个已经继承了父类的子类,就不能再继承Thread类,这时就可以用Runnable接口实现多线程。
3, 有利于程序的健壮性,代码和数据都可以被多个线程共享。当线程被开辟时,只需要把一个实现了代码和数据(如上面代码中的new TestThread)的对象(如上面代码中的tt)传入,此时的这个对象就是一个实现了Runnable接口的实例。
前(后)台线程:(后台线程也叫守护线程)
对JAVA程序来说,只要还有一个前台线程在运行,程序就不会结束。只有当程序只有后台线程在运行的时候,程序才会结束。
对于上面的程序来说,永远不会结束,因为前台线程是一个无限循环。
如果在new Thread(tt).start()前加上一句new Thread(tt).setDaemon(true);就会将该线程变为后台线程。
可以这么理解:前台循环有硬性规定(必须全部执行完)
多线程的同步:(只有涉及到线程安全的时候再使用)
使用同步的时候,所共享的数据,要设置为private。这样不会被外部访问或修改,可以保持一致性。
卖票系统中:有一个if(tickets>0)的判断,假设现在票数为1,执行判断结果为真。
就在此时,也许会突然转换为另一个线程(这个由cpu控制,有这种可能发生)。
这时在另一个线程tickets仍然为1,票数是共享的,所以在另一个线程结束后,票数会减1,此时的tickets是 0。
返回之前的线程湖,因为之前判断的时候,tickets是1,而此时tickets为0,打印出来的是0,如果线程多,还有可能出现-1,-2等。这样就会出现错误。(习惯称为线程安全问题)
概念性的东西太多 我也没学好 就不多说了........
使用Thread来实现多线程,弊端比较多,不建议使用。
Runnable接口(最常用的实现多线程的接口,建议使用)
Runnable 接口 相对于 继承Thread类来说,有以下优点:
1, 适合多个相同程序的代码(同一段代码,开辟N个线程)去处理同一个资源(比如联网售票,票的个数是共同的)的情况。// 把线程(售票点),实现代码(卖票)和数据(票)有效的分离开,较好的实现了面向对象的设计思想。
2, 可以避免由于java的单继承特性所带来的局限性。比如:一个已经继承了父类的子类,就不能再继承Thread类,这时就可以用Runnable接口实现多线程。
3, 有利于程序的健壮性,代码和数据都可以被多个线程共享。当线程被开辟时,只需要把一个实现了代码和数据(如上面代码中的new TestThread)的对象(如上面代码中的tt)传入,此时的这个对象就是一个实现了Runnable接口的实例。
前(后)台线程:(后台线程也叫守护线程)
对JAVA程序来说,只要还有一个前台线程在运行,程序就不会结束。只有当程序只有后台线程在运行的时候,程序才会结束。
对于上面的程序来说,永远不会结束,因为前台线程是一个无限循环。
如果在new Thread(tt).start()前加上一句new Thread(tt).setDaemon(true);就会将该线程变为后台线程。
可以这么理解:前台循环有硬性规定(必须全部执行完)
多线程的同步:(只有涉及到线程安全的时候再使用)
使用同步的时候,所共享的数据,要设置为private。这样不会被外部访问或修改,可以保持一致性。
卖票系统中:有一个if(tickets>0)的判断,假设现在票数为1,执行判断结果为真。
就在此时,也许会突然转换为另一个线程(这个由cpu控制,有这种可能发生)。
这时在另一个线程tickets仍然为1,票数是共享的,所以在另一个线程结束后,票数会减1,此时的tickets是 0。
返回之前的线程湖,因为之前判断的时候,tickets是1,而此时tickets为0,打印出来的是0,如果线程多,还有可能出现-1,-2等。这样就会出现错误。(习惯称为线程安全问题)
概念性的东西太多 我也没学好 就不多说了........