多线程与并发----线程互斥技术

柔光的暖阳◎ 2021-09-15 09:42 587阅读 0赞

1、使用synchronized代码块

2、使用synchronized方法

3、分析静态方法锁使用的同步监视器对象是什么?

4、wait与notify实现线程间的通信

例一:使用内部类和两个线程交替不停的打印lisi和zhangsan两个名字

  1. public class ThreadSynchronized {
  2. public static void main(String[] args) {
  3. new ThreadSynchronized().init();
  4. }
  5. public void init(){
  6. /*在静态方法中不能new内部类的实例对象,
  7. 因为内部类的最重要的一个特点就是它可以直接访问它外部类的成员变量。成员变量是对象身上的。对象创建完成了,才会为成员变量分配空间。能调用成员变量,意味着一定有了实例对象.
  8. main方法是静态的,它执行的时候可以不用创建那个对象。这就矛盾了。
  9. */
  10. final Outputer outputer=new Outputer();//创建内部类
  11. new Thread(new Runnable() {//创建一个线程
  12. public void run() {
  13. while(true){
  14. try {
  15. Thread.sleep(1000);
  16. } catch (InterruptedException e) {
  17. e.printStackTrace();
  18. }
  19. outputer.output("lisi");
  20. }
  21. }
  22. }).start();
  23. new Thread(new Runnable() {//创建一个线程
  24. public void run() {
  25. while(true){
  26. try {
  27. Thread.sleep(1000);
  28. } catch (InterruptedException e) {
  29. e.printStackTrace();
  30. }
  31. outputer.output("zhangsan");
  32. }
  33. }
  34. }).start();
  35. }
  36. //内部类
  37. class Outputer{
  38. public void output(String name){
  39. int len=name.length();
  40. synchronized (name)
  41. {
  42. for(int i=0;i<len;i++){
  43. System.out.print(name.charAt(i));
  44. }
  45. System.out.println();
  46. }
  47. }
  48. }
  49. }

运行结果为:

lisi
zhangsan
zhangsan
lisi
lisi
zhangsan
lisi

使用synchronized代码块

  1. public class ThreadSynchronized {
  2. public static void main(String[] args) {
  3. new ThreadSynchronized().init();
  4. }
  5. public void init(){
  6. /*在静态方法中不能new内部类的实例对象,
  7. 因为内部类的最重要的一个特点就是它可以直接访问它外部类的成员变量。成员变量是对象身上的。对象创建完成了,才会为成员变量分配空间。能调用成员变量,意味着一定有了实例对象.
  8. main方法是静态的,它执行的时候可以不用创建那个对象。这就矛盾了。
  9. */
  10. final Outputer outputer=new Outputer();//创建内部类
  11. new Thread(new Runnable() {//创建一个线程
  12. public void run() {
  13. while(true){
  14. try {
  15. Thread.sleep(1000);
  16. } catch (InterruptedException e) {
  17. e.printStackTrace();
  18. }
  19. outputer.output("lisi");
  20. }
  21. }
  22. }).start();
  23. new Thread(new Runnable() {//创建一个线程
  24. public void run() {
  25. while(true){
  26. try {
  27. Thread.sleep(1000);
  28. } catch (InterruptedException e) {
  29. e.printStackTrace();
  30. }
  31. outputer.output("zhangsan");
  32. }
  33. }
  34. }).start();
  35. }
  36. //内部类
  37. class Outputer{
  38. public void output(String name){
  39. int len=name.length();
  40. synchronized (this)
  41. {
  42. for(int i=0;i<len;i++){
  43. System.out.print(name.charAt(i));
  44. }
  45. System.out.println();
  46. }
  47. }
  48. }
  49. }

使用synchronized方法

  1. public class ThreadSynchronized {
  2. public static void main(String[] args) {
  3. new ThreadSynchronized().init();
  4. }
  5. public void init(){
  6. /*在静态方法中不能new内部类的实例对象,
  7. 因为内部类的最重要的一个特点就是它可以直接访问它外部类的成员变量。成员变量是对象身上的。对象创建完成了,才会为成员变量分配空间。能调用成员变量,意味着一定有了实例对象.
  8. main方法是静态的,它执行的时候可以不用创建那个对象。这就矛盾了。
  9. */
  10. final Outputer outputer=new Outputer();//创建内部类
  11. new Thread(new Runnable() {//创建一个线程
  12. public void run() {
  13. while(true){
  14. try {
  15. Thread.sleep(1000);
  16. } catch (InterruptedException e) {
  17. e.printStackTrace();
  18. }
  19. outputer.output("lisi");
  20. }
  21. }
  22. }).start();
  23. new Thread(new Runnable() {//创建一个线程
  24. public void run() {
  25. while(true){
  26. try {
  27. Thread.sleep(1000);
  28. } catch (InterruptedException e) {
  29. e.printStackTrace();
  30. }
  31. outputer.output("zhangsan");
  32. }
  33. }
  34. }).start();
  35. }
  36. //内部类
  37. class Outputer{
  38. public synchronized void output(String name){
  39. int len=name.length();
  40. for(int i=0;i<len;i++){
  41. System.out.print(name.charAt(i));
  42. }
  43. System.out.println();
  44. }
  45. }
  46. }

20180508172624998

例子:子线程循环10次和主线程循环10次,两者实现同步

  1. public class ThreadCommunication {
  2. public static void main(String[] args) {
  3. final Business business=new Business();
  4. new Thread(new Runnable() {
  5. public void run() {
  6. for(int i=0;i<50;i++){
  7. business.sub(i);
  8. }
  9. }
  10. }).start();
  11. for(int i=0;i<50;i++){
  12. business.main(i);
  13. }
  14. }
  15. }
  16. class Business{
  17. public synchronized void sub(int i){
  18. for(int j=0;j<10;j++){
  19. System.out.println("sub thread sequence of"+j+",loop of"+i);
  20. }
  21. }
  22. public synchronized void main(int i){
  23. for(int j=0;j<100;j++){
  24. System.out.println("main thread sequence of"+j+",loop of"+i);
  25. }
  26. }
  27. }

例子:子线程循环10次和主线程循环10次,两者交替运行50次的例子

  1. public class ThreadCommunication {
  2. public static void main(String[] args) {
  3. final Business business=new Business();
  4. new Thread(new Runnable() {
  5. public void run() {
  6. for(int i=0;i<50;i++){
  7. business.sub(i);
  8. }
  9. }
  10. }).start();
  11. for(int i=0;i<50;i++){
  12. business.main(i);
  13. }
  14. }
  15. }
  16. class Business{
  17. private boolean bSholdSub=true;
  18. public synchronized void sub(int i){
  19. if(!bSholdSub){
  20. try {
  21. this.wait();
  22. } catch (InterruptedException e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. for(int j=0;j<10;j++){
  27. System.out.println("sub thread sequence of"+j+",loop of"+i);
  28. }
  29. bSholdSub=false;
  30. this.notify();
  31. }
  32. public synchronized void main(int i){
  33. if(bSholdSub){
  34. try {
  35. this.wait();
  36. } catch (InterruptedException e) {
  37. e.printStackTrace();
  38. }
  39. }
  40. for(int j=0;j<10;j++){
  41. System.out.println("main thread sequence of"+j+",loop of"+i);
  42. }
  43. bSholdSub=true;
  44. this.notify();
  45. }
  46. }

运行结果为:

sub thread sequence of0,loop of0
sub thread sequence of1,loop of0
sub thread sequence of2,loop of0
sub thread sequence of3,loop of0
sub thread sequence of4,loop of0
sub thread sequence of5,loop of0
sub thread sequence of6,loop of0
sub thread sequence of7,loop of0
sub thread sequence of8,loop of0
sub thread sequence of9,loop of0
main thread sequence of0,loop of0
main thread sequence of1,loop of0
main thread sequence of2,loop of0
main thread sequence of3,loop of0
main thread sequence of4,loop of0
main thread sequence of5,loop of0
main thread sequence of6,loop of0
main thread sequence of7,loop of0
main thread sequence of8,loop of0

main thread sequence of9,loop of0

sub thread sequence of0,loop of0

为了观察程序的运行结果,可以在myeclipse中设置运行对话框,让结果重定向到一个文本文件,然后去查看该文本文件中的特殊行号是否正好对应了线程的切换点。

RUN AS—>Run Configurations—>右边Common—>File前面打钩,—》输入路径,比如输入C:\Users\Administrator\Desktop\1.txt,最后点击run,就可在选择路径下看到运行程序的结果。

20180510215051947

经验:要用到共同数据(包括同步锁)的若干个方法应该归在同一个类上,这个设计正好体现了高内聚和程序的健壮性。

发表评论

表情:
评论列表 (有 0 条评论,587人围观)

还没有评论,来说两句吧...

相关阅读

    相关 线-互斥

    多线程线程同步机制是为是各线程能够协同工作而设计的。 Windows系统中有很多种机制可以用于线程同步,最常用的有下面几种: ◇互斥对象( Mutex); ◇ 事件