2020-11-07多线程

一、多线程

  • 工厂模式
  • 单利模式
  • 代理模式

1.单例模式(Singleton):

注意:

  1. 单例类只能有一个实例
  2. 单利必须自己创建自己的唯一实例
  3. 单例类必须含有所有其他对象提供这一实例

2.饿汉式单利

public class Calendar {
    private final static Calendar CALENDAR = new Calendar ();
    private Calendar(){};
    public static Calendar getInstance(){
        return CALENDAR;
    }
}

3.懒汉式单利

public class Calendar2 {
   //需要一个静态的成员变量保存咋们的实例;
    private static Calendar2 CALENDAR2 ;
    //私有化构造器,不让外边new;
    private Calendar2(){};
    //持有一个方法,这个方法能返回内存当中的实例;
    public static Calendar2 getInstance(){
        if (CALENDAR2 == null){
            CALENDAR2 = new Calendar2 ();
        }
        return CALENDAR2;
    }
}

4.字符串变成数组统计中元素的个数

package com.xinzhi;

import java.util.HashMap;
import java.util.Map;

/**
 * @author:荆少奇
 * @create:2020/11/7 16:04
 *
 */
public class Test1 {
    public static void main(String[] args) {
        String content = "hello world hello world aa" + "bb cc db cc ww qq xx xxx";
        //1.先全部搞成小写
        content = content.toLowerCase ();
        //2.字符串搞成数组
        String[] worlds = content.split ("");
        //3.创建一个hashmap保存结果
        Map<String,Object> result = new HashMap<> (16);
        //4.循环遍历数据一个单词一个单词看
        for (String word:worlds){
            //看一看hasmap里有没有这个key
            //有的话value+1
            if(result.containsKey (word)){
                result.put (word,(Integer)result.get (word) + 1);
            }else{
                //没有的话放进去(word+1)
                result.put (word,1);
            }
            //hashmap便利
            for(Map.Entry<String, Object> entry:result.entrySet ()){
                System.out.println (entry.getKey () + "出现" + entry.getValue () + "次了");
            }




        }
    }

}

5.归并的思想和对比

package com.xinzhi;

/**
 * @author:荆少奇
 * @create:2020/11/7 15:15
 */
public class Test {

    public static void main(String[] args) {
       int[] arr1 = {1,3,5};
       int[] arr2 = {2,4,6};
       int[] concat = concat (arr1,arr2);

        //把两个有序数组合并成一个数组,还有序
        for (int i:concat){
            System.out.println (i + " ");
        }
    }
    private static int[] concat(int[] arr1,int[] arr2) {

        //1.创建一个新数组
        int[] temp = new int[arr1.length + arr2.length];

        int left = 0;
        int right = 0;
        int newIndex = 0;

        //退出循环的机制
        while (arr1.length != left && arr2.length != right){
            if (arr1[left] > arr2[right]){
                temp[newIndex] = arr2[right];
                right++;
            }else {
                temp[newIndex] = arr1[left];
                left++;
            }
            newIndex++;
        }

        if(arr1.length == left){
            for (int i = right; i < arr2.length;i++){
                temp[newIndex++] = arr2[i];
            }

        }

        if(arr2.length == right){
            for (int i = left; i < arr1.length;i++){
                temp[newIndex++] = arr1[i];
            }

        }

        return temp;
    }
}

二、多进程

电脑开了很多应用程序,一个程序一个进程

一个进程里边包含很多线程

Thread:

  1. currentThread : 显示当前线程

  2. Thread.sleep: 让线程睡几毫秒

  3. start(): 开启一个新的线程

    package currentThreadAndThis;
    public class MyThread extends Thread {
        public MyThread(){
            System.out.println("当前线程的名字:"+Thread.currentThread().getName());
            System.out.println("当前线程的名字:"+this.getName());
        }
        @Override
        public void run(){
            System.out.println("当前线程的名字:"+Thread.currentThread().getName()+"   run=="+Thread.currentThread().isAlive());
            System.out.println("当前线程的名字:"+this.getName()+"  run=="+this.isAlive());
        }
    }
    
    //启动类
    package currentThreadAndThis;
    public class Run {
        public static void main(String[] args) {
            MyThread myThread=new MyThread();
            //初始化Thread对象,方便调用start();
            //此时myThread作为参数传入Thread中,其实是myThread委托thread去执行;
            Thread thread=new Thread(myThread);
            //初始化自定义线程名称
            thread.setName("C");
            //启动线程
            thread.start();
    
        }
    }
    

运行结果

  1. 当前线程的名字:main
  2. 当前线程的名称:Thread-0
  3. 当前线程的名字:C run == tru
  4. 当前线程的名字:Thread-0 run ==false**

并发

同时拥有两个或多个线程,如果程序在单核处理器上运行,多个线程将交替地换入或者换出内存,这些线程是同时「 存在 」的,每个线程都处于执行过程中的某个状态,如果运行在多核处理器上,此时,程序中每个线程都将分配到一个处理器核上,因此可以同时运行。并发就是多个线程操作相同的物理机中的资源,保证其线程安全,合理的利用资源。

三、线程安全问题初探(vector和hashTap)

1.异常

顶级父类:Throwable

Error 错误 :一旦发生错误程序就直接崩溃

Exception 异常:异常分为受查异常和运行时异常

受查异常:手动提前处理

运行时异常:手动做好检查

1. 返回异常发生时的详细信息
public string getMessage();
2. 返回异常发生时的简要描述
public string toString();
3. 返回异常对象的本地化信息。使用Throwable的子类覆盖这个方法,可以声称本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与getMessage()返回的结果相同
public string getLocalizedMessage();
4. 在控制台上打印Throwable对象封装的异常信息
public void printStackTrace();

四、Exception:异常

1.处理异常

1. 抛出异常(throws):当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息。

2. 捕获异常:在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exception handler)。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。

try{

}catch{

}

printStackTrace:能打出异常在哪

2.throws和throw有什么不同

位置不同:throws用在函数上,后面跟的是异常类,可以跟多个。

throw用在函数内,后面跟的是异常对象。

功能不同:throws用来声明异常,让调用者知道该功能有可能出现的问题,并由调用者给出预先的处理方式。

throw抛出具体问题的对象。语句执行到throw功能就结束了,跳转到调用者。并将具体的问题对象抛给调用者。

注意:throw语句独立存在,下面不要定义其他语句。因为执行不到throw下面的语句。

3.线程安全

线程安全是指多个线程在执行同一段代码的时候采用加锁机制,使每次的执行结果和单线程执行的结果都是一样的,不存在执行结果的二义性。
线程不安全就是不提供加锁机制保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据

4.解决多线程不安全的问题:

synchronizd:同步锁

1)同步代码块:
synchronized(同步锁)
{
     //方法体
}
(2)同步方法:给多线程访问的成员方法加上synchronized修饰符
public synchronized  void test(){
     //方法体
}

5.String,StringBuilder,StringBuffer

运行速度:

StringBuilder > StringBuffer > String

在线程安全上:

StringBuilder是线程不安全的,而StringBuffer是线程安全的

  • String:适用于少量的字符串操作的情况
  • StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
  • StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况

[图片上传失败...(image-d54150-1604755558371)]

[图片上传失败...(image-4c8640-1604755558371)]

[图片上传失败...(image-d30ab2-1604755558371)]

[图片上传失败...(image-d8c778-1604755558371)]

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。