java多线程

 java 多线程是在java中常用到的技术, 下面先从一个最简单的线程创建开始讲起。

 

多线程 的好处:
1. 解决一个进程中可以同时执行多个任务的问题。
2. 提高了资源利用率。

多线程的弊端:
1. 增加了cpu的负担。
2. 降低了一个进程中线程 的执行概率。
3. 出现了线程 安全问题。
4. 会引发死锁现象。

自定义线程 的实现方式:

方式一 :
1. 自定义一个类继承Thread类。
2. 重写Thread类的run方法,把自定义线程的任务代码写在run方法上。
3. 创建Thread的子类对象,并且调用start方法启动一个线程。

注意:千万不要直接调用run方法,调用start方法的时候线程就会开启,线程一旦开启就会执行run方法中代码,如果直接调用run方法,那么就 相当于调用了一个普通的方法而已。

//创建一个类让这个类继承Thread类,这个类就是个线程类了。
public class Demo1 extends Thread {

    //重写此类的构造函数,给这个线程起一个名称
    public  Demo1(String name){
        
        super(name);
        
    }
    
    //重写父类的run方法
    public  void run() {
        
        //输出从1到100
        for(int i=0;i<100;i++){
        
            System.out.println(this.getName()+i);
        }
    }
    
    public static void main(String[] args) throws Exception{
        
        //实例化线程
        Demo1 dome=new  Demo1("徐周");
        
        //给当前线程定一个暂定时间,暂定时间结束后线程继续执行
        dome.sleep(1000);
         
        //起动线程,从start()开始线程才开始真正等待CPU动行
        dome.start();
         
        //输出当前线程的优先级别java线程一共10个级别1-10
        System.out.println(dome.getPriority());
         
        //输出主线程的优先级别
         System.out.println(Thread.currentThread().getPriority());
          
         for (int i = 0; i < 100; i++) {
            
             System.out.println("dddd主线程");
        }
        
        
    }

}

 

一个最简单的java多线程就写完了,下面我们再来看线程安全问题。

package com.xuzhou;

 
public class xuzhou2 extends Thread {

     static int sum=50;
     
     static Object o=new Object();
    
    public xuzhou2(String name){
        
        super(name);
    }
    @Override
    public void run() {
        
        while(true){
                            
                if(sum>0){
                                        System.out.println(Thread.currentThread().getName()+"出售了第"+sum+"张票");
                    
                    sum--;
                }else{
                    
                    
                    System.out.println("票已经卖完了");
                    
                    break;
                }
            
            
        }
        
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        
        xuzhou2 mode1=new  xuzhou2("窗口1");
        xuzhou2 mode2=new  xuzhou2("窗口2");
        xuzhou2 mode3=new  xuzhou2("窗口3");

         mode1.start();
         mode2.start();
         mode3.start();
         
        
         
    }

}

  

运行这段代码,我们会发现一个问题,就是同一个数据会出现2次,为什么这样呢?我们已经定义了 static int sum=50 为静态成员了,但运行的时候还是会出现sum相同的数据,这次是线程安全问题,因为CPU会抢资源,3个线程都在操作一个run方法,
当一个线程刚刚输出System.out.println(Thread.currentThread().getName()+"出售了第"+sum+"张票");的时候还没来得急Sum--,这个时候CPU有可能就会抢资源,第二个线程这个时候进来了,所以就会造成输出相同的数,出现线程安全问题。

  程安全出现 的根本原因:
  1. 存在两个或者两个以上 的线程对象共享同一个资源。
  2. 多线程操作共享资源的代码 有多句。

这个问题怎么解决呢,其实很好解决在run方法里面加一个synchronized ("锁")就行,如下:
package com.xuzhou;

 
public class xuzhou2 extends Thread {

     static int sum=50;
     
     static Object o=new Object();
    
    public xuzhou2(String name){
        
        super(name);
    }
    @Override
    public void run() {
        
        while(true){
            synchronized ("锁") {
                
                if(sum>0){
                    
                    System.out.println(Thread.currentThread().getName()+"出售了第"+sum+"张票");
                    
                    sum--;
                }else{
                    
                    
                    System.out.println("票已经卖完了");
                    
                    break;
                }
            }
            
        }
        
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        
        xuzhou2 mode1=new  xuzhou2("窗口1");
        xuzhou2 mode2=new  xuzhou2("窗口2");
        xuzhou2 mode3=new  xuzhou2("窗口3");

         mode1.start();
         mode2.start();
         mode3.start();
         
        
         
    }

}

  运行这段代码,就不会再出现线程安全的问题了,为什么加上synchronized (锁对象)就不会出现线程安全问题呢?

java中每个对象都有一个锁,默认对象是没有加锁的,当我们加上synchronized (锁对象)时,这个对象就会锁住了,当这个对象被锁住时,别的进程就无法访问些对象了,只有当前进程出了这个ynchronized (锁对象)时 ,对象会再次打开,别的进程才能进来,这样就不会出现 线程安全问题了。

  同步函数synchronized要注意的事项 :
  1. 如果是一个非静态的同步函数的锁 对象是this对象,如果是静态的同步函数的锁 对象是当前函数所属的类的字节码文件(class对象)。
  2. 同步函数的锁对象是固定的,不能由你来指定 的。

 

 

 

先写到这,有时间一点一点完善。

原文地址:https://www.cnblogs.com/xu3593/p/5716396.html