java线程的几个问题

  • 为什么要实现run方法?
  • Thread类用于描述线程。该类定义了一个功能,用于存储线程要运行的代码,该存储功能就是run()方法。即run方法用来存储代码。
  • 为什么直接调用run方法达不到交替效果而是一个执行完在执行另一个?
  • 因为子线程没有运行,start是开启线程并执行线程的run方法。 d.run()仅仅是对象调用方法,而线程创建了并没有运行。
  • 为什么进行线程同步?
  • 多条语句在操作同一个线程共享数据时,一个线程对多条共享语句只执行一部分,还没执行完,另外一个线程参与进来执行,导致共享数据被使用时的数据大小与正常存在差异。解决办法是,对多条包含共享数据的语句,只能让一个线程所有共享语句都执行完,才允许其他线程参与进来,于是引入了同步。关键字为:synchronized
  • 代码写法
  • 同步代码块
synchronized(同步对象){
  需要同步的代码块;
}
  • 同步方法
synchronized void 方法名称(){}
  • 窗口买票为例:
  • myRunnable.java
public class myRunnable implements Runnable {
  private int a = 100;
    @Override
    public void run() {
        for (int i = 0; i <25 ; i++) {
            if(a>0){
                a--;
                System.out.println("剩余票数:"+a+"窗口"+Thread.currentThread().getName());
            }else {
                continue;
            }
        }
    }
}
  • ThreadTest.java
public class ThreadTest {
    public static void main(String[] args) {
      myRunnable r1 = new myRunnable();
      new Thread(r1).start();
      new Thread(r1).start();
      new Thread(r1).start();
      new Thread(r1).start();
    }
}
  • 执行结果
剩余票数:98窗口Thread-0
剩余票数:96窗口Thread-3
剩余票数:97窗口Thread-2
剩余票数:98窗口Thread-1
剩余票数:94窗口Thread-2
剩余票数:95窗口Thread-3
剩余票数:93窗口Thread-0
  • 发现问题
  • 有两个98张,这两个方法都存在这种状况,线程缺少同步。
  • 解决办法
  • 第一种:同步
//myRunnable.java
public class myRunnable implements Runnable {
  private int a = 100;
    @Override
    public void run() {

        for (int i = 0; i <25 ; i++) {
            synchronized (this){
                if(a>0){
                    a--;
                    System.out.println("剩余票数:"+a+"窗口"+Thread.currentThread().getName());
                }else {
                    continue;
                }
            }
        }
    }
}
  • 执行结果:不再存在重复
剩余票数:99窗口Thread-0
剩余票数:98窗口Thread-0
剩余票数:97窗口Thread-0
剩余票数:96窗口Thread-0
剩余票数:95窗口Thread-0
剩余票数:94窗口Thread-0
剩余票数:93窗口Thread-0
  • 第二种:以同步方法的形式
public class myRunnable implements Runnable {
    private int a = 100;
    @Override
    public void run() {
        for (int i = 0; i < 25; i++) {
            try {
                tell();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public synchronized void tell() throws InterruptedException {
        if (a > 0) {
            a--;
            System.out.println("剩余票数:" + a + "窗口" + Thread.currentThread().getName());
        }
    }
}
  • 执行结果
剩余票数:99窗口Thread-0
剩余票数:98窗口Thread-0
剩余票数:97窗口Thread-0
剩余票数:96窗口Thread-0
剩余票数:95窗口Thread-0
剩余票数:94窗口Thread-0
剩余票数:93窗口Thread-0
  • java多线程中使用同步,那么和单线程有什么区别呢?
  • 多线程同步,宏观上是多条执行流水线在同时执行run方法的基础上,排队有序执行syn锁内方法。
  • 单线程只是一条执行流水线执行run()方法里面代码,与多线程同步联系不大。
  • 其他网站回答
  • 线程同步是指当大家共用同一个东西的时候才有必要,使用资源一般只是在程序执行流程的某个环节,多数时间它们是在处理而不是操作资源,比如程序处理完数据后保存到磁盘就只是在保存时使用资源,而处理的时候不使用资源,我们同步仅对使用资源加锁,处理数据的部分是可以同时并行的,所以我们的桌面型[操作系统]允许多个任务同时运行,只是在访问磁盘时内部细节中加锁轮,当磁盘机械装置转到哪个扇区时就允许哪个程序来访问。我们不能对所有的东西都用 synchronized,仅对有可能导致冲突和状态不一致的代码加 synchonized 来锁定这块区域,就是说进入这个块区域之前必须申请锁而且得到锁后运行时其它线程在它释放锁之前不能访问,如果其它线程当前还在处理数据并没有打算使用这个资源的时候就可以在另一个线程中并行运行。
  • 关于同步一些总结
  • 同步会对多线程的效果产生影响,但是只是一小部分(资源数理部分)。举个例子,以单核cpu为例,假设有3个线程A,B,C(假设优先级一样),cpu在某个时间片段只能执行一次,A抢去执行权,执行一会(没到同步块),执行权被C抢去,执行一会,再次被A抢去,执行同步快,这是cpu执行权会被锁定在A的同步块,其他线程不再能抢夺执行权,直到等到同步快的内容执行完之后,执行权才能被线程抢夺。多核cpu,比如3核,A,B,C线程同时执行,执行到同步区,某一时间段只能执行一个线程的同步块,执行完自后,自己接着走,其他线程抢同步块的执行权;2核有一方要抢,所有的执行权,原理一样;