javaSE入门总结(个人学习)---第六部分:集合、多线程

一、集合

1、什么是集合
概念: 对象的容器存储对象的对象,可代替数组
和数组区别:(1)、数组长度固定,集合长度不固定。(2)、数组可以存在基本类型和引用类型,集合只能存在引用类型。
特点: 容器的工具类,定义了对多个对象进行操作的常用方法
位置: java.util.*;

在这里插入图片描述

2、Collection接口
特点: 代表一组任意类型的对象无序无下标
Collection常用方法

Arraylist.add(Object obj) //添加一个对象
Arraylist.addAll(Collection c) //将一个集合中的所有对象添加到此集合
clear() //清空此集合中的所有对象
Arraylist.contains(Object o) //检查此集合中是否包含o对象
Arraylist.equals(Object o) //比较此集合是否与指定对象相等
Arraylist.idEmpty() //判断此集合是否为空
Arraylist.remove(Object o) //在此集合中移除o对象
.size() //返回此集合中的元素个数
Arraylist.toArray() //将此集合转换成数组
//方法使用
public class textArrayList{
	public static void main(String[] args){
		//创建ArrayList
		Collection arr = new ArrayList();
		//add添加元素
        arr.add("ABC");
        arr.add("DEG");
        arr.add("HIM");
        
        System.out.println(arr);//结果:[ABC, DEG, HIM]
        System.out.println("元素个数:"+arr.size());//结果:元素个数:3
        
        arrayList.remove("ABC");
        System.out.println(arr);//结果:[DEG, HIM]
}
}

3、List子接口
特点: 有序、有下标、元素可以重复

List实现类
ArrayList(重点)
数组结构实现,查询快、增删慢
JDK1.2版本,运行效率快、线程不安全
Vector
数组结构实现,查询快、增删慢
JDK1.0版本,运行效率慢、线程安全
LinkedList
链表结构实现,增删快,查询慢

List常用方法

Arraylist.add(int index, Object o) //在index位置插入对象o
Arraylist.addAll(int index, Collection c) //将一个集合中的元素添加到集合中的index位置
Arraylist.get(int index) //返回集合中指定位置的元素
Arraylist.subList(int fromIndex, int toIndex) //返回fromIndex和toIndex之间的集合元素
public class textArrayList{
	public static void main(String[] args){
		List list = new ArrayList();
    	list.add("abc");
    	list.add("ghi");
    	list.add(1,"def");
    	System.out.println(list);//结果:[abc, def, ghi]
    	list.addAll(0,arrayList);
    	System.out.println(list);//结果:[DEG, HIM, abc, def, ghi]
	}
}

4、Set子接口
特点: 无序、无下标、元素不可重复
方法: 全部继承自Collection中的方法

Set实现类
HashSet
基于HashCode实现元素不重复
当存入元素的哈希码相同时,会调用equals进行确认,如结果为true,则拒绝后者存入
LinkedHashSet
链表实现的HashSet,按照链表进行存储,即可保留元素的插入顺序
TreeSet
基于排列顺序实现元素不重复
实现了SortedSet接口,对集合元素自动排序
元素对象的类型必须实现Comparable接口,指定排序规则
通过CompareTo方法确定是否为重复元素

5、Map接口
在这里插入图片描述
特点: 存储一对数据(Key-Value),无序、无下标,键不可重复,值可重复

map接口常用方法

map.put(K key, V value) //将对象存入到集合中,关联键值。key重复则覆盖原值
map.get(Object key) //根据键获取对应的值
keySet //返回所有key
Collection values() //返回包含所有值的Collection集合
Set<Map.Entry<K, V>> //键值匹配的Set集合
public class textArrayList{
	public static void main(String[] args){
		Map map = new HashMap();
        map.put("one","你好");
        map.put("twe","世界");
        System.out.println(map);//结果:{twe=世界, one=你好}
        System.out.println(map.get("one"));//结果:你好
        System.out.println(map.keySet());//结果:[twe, one]
        System.out.println(map.values());//结果:[世界, 你好]
	}
}

Map实现类
HashMap
JDK1.2版本,线程不安全,运行效率快;允许用null 作为key或是value
Hashtable
JDK1.0版本,线程安全,运行效率慢;不允许用null作为key或是value
Properties
Hashtable的子类,要求key和value都是String。通常用于配置文件的读取
TreeMap
实现了SortedMap接口(是Map子接口),可以对key自动排序

6、增强for
可遍历集合或数组

for(数据类型 变量名 : 容器名称){ //可遍历集合或数组(常用在无序集合上)
	//System.out.println();
}
for (Object string : map.values()){
            System.out.println(string);
        }
        /*结果: 世界
				你好
		*/

小总结

  • 集合的概念
    对象的容器,存储对象的对象,定义了对多个对象进行操作的常用方法
  • List集合
    有序、下标、元素可以重复。(ArrayList、LinkedList、Vector)
  • Set集合
    无序、下标、元素不可重复。(HashSet、LinkedHashSet、TreeSet)
  • Map集合
    存储一对数据,无序、无下标,键不可重复,值可重复。(HashMap、HashTable)
  • Collections
    集合工具类,定义了除了存取以外的集合常用方法

二、多线程

1、简单了解

什么是进程在这里插入图片描述
程序是静止的,只有真正运行的程序才被称为进程

什么是线程
线程,又称轻量级进程
程序中的一个顺序控制流程,同时也是CPU的基本调度单位

  • 就如,网盘是一个进程,当中的多个下载任务就是多个线程。
  • jvm是一个进程,当中默认包含主线程(Main函数),可通过代码创建多个独立线程,与Main并发执行
2、线程组成
  • CPU时间片: 操作系统(OS)会为每个线程分配时间
  • 堆空间: 存储线程需使用的对象,多个线程可以共享堆中的对象
    栈空间: 存储线程需使用的局部变量,每个线程都拥有独立的栈
  • 线程的逻辑代码
创建线程
//第一种方式
public class textThread{
	public static void main(String[] args){
		//new进行创建
		Son son = new Son();
		son.start();//start()方法启动
	}
}
//extends thread类
class Son extends Thread{
	//重写run
	@Override
	public void run(){
		···实现代码
	}
}
//第二种方式
public class textThread{
	public static void main(String[] args){
		//new进行创建
		Son son = new Son();
		//new Thread进行
        Thread thread = new Thread(son);
        thread.start();//start()方法启动
	}
}
//实现Runnable接口
class Son implements Runnable{
	//重写run
    @Override
    public void run() {
        ···实现代码
    }
}

3、线程的状态

基本状态
在这里插入图片描述
线程休眠

.sleep(long millis);
//millis毫秒:1000millis=1s

睡眠的位置:为了让其他线程有机会执行,可以将Thread.sleep()的调用 放线程run()之内。这样才能保证该线程执行过程中会睡眠。

public class textSleep {
    public static void main(String[] args) {
        Son son = new Son();
        son.start();
    }
}
class Son extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("sleep"+i);
            //在for里面,让线程输出一次就睡眠1s
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //让线程输出完for就睡眠2s
        try {
            sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //睡眠2s后运行
        for (int i = 0; i < 5; i++) {
            System.out.println("peels"+i);
        }
    }
}

注意点:
1、线程睡眠是帮助所有线程获得运行机会的最好方法。
2、线程睡眠到期自动苏醒,并返回到可运行状态,不是运行状态。 sleep()中指定的时间是线程不会运行的最短时间。因此,sleep()方法不能保证该线程睡眠到期后就开始执行。
3、sleep()是静态方法,只能控制当前正在运行的线程。

线程放弃

.yield()
//当前线程主动放弃时间片,回到就绪状态,竞争下一次时间片
public class text10 {
    public static void main(String[] args) {
    	Son2 son2 = new Son2();
        son2.start();
        Son1 son = new Son1();
        son.start();
    }
}
class Son2 extends Thread{
    @Override
    public void run() {
        yield();//主动放弃时间片
        for (int i = 0; i < 5; i++) {
            System.out.println("yield"+i);
        }
    }
}
class Son1 extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("sleep"+i);
            try {
                sleep(1000);//睡眠1s看看
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

结果:在这里插入图片描述

线程结合

.join()
//允许其他线程加入到当前线程中,等待加入的线程执行完毕后,此线程再去竞争时间片执行
public class textJoin{
	public static void main(String[] args){
		//new创建son3就行
		Son3 son = new Son3();
		son.start();
	}
}
class Son3 extends Thread{
	// 创建son4
    Son4 son4 = new Son4();
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("我"+i);
        }
        try {
            son4.start();//start方法准备
            son4.join();//结合son4
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class Son4 extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(i);
        }
    }
}
4、线程安全

线程安全问题
在这里插入图片描述
这样可能会造成数据错误问题

解决线程安全问题的方法
进行同步代码块、同步方法

//对临界资源对象加锁
synchronized(临界资源对象) {
		代码(原子操作)
}
//对当前对象(this)加锁
synchronized 返回值类型 方法名称(形参列表0) {
	代码(原子操作)
}

synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:
  1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
  2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
  3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
  4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

修饰一个代码块

public class textThread {
    public static void main(String[] args) {
        textSynchThread sy = new textSynchThread();
        Thread thread = new Thread(sy);
        Thread thread1 = new Thread(sy);
        thread.start();
        thread1.start();

    }
}
class textSynchThread implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("线程" + i);
        }
        /*
        synchronized(this) {
            for (int i = 0; i < 10; i++) {
                System.out.println("线程" + i);
            }
        }
        */
    }
}

结果:在这里插入图片描述

public class text11 {
    public static void main(String[] args) {
        textSynchThread sy = new textSynchThread();
        Thread thread = new Thread(sy);
        Thread thread1 = new Thread(sy);
        thread.start();
        thread1.start();

    }
}
class textSynchThread implements Runnable{
    @Override
    public void run() {
        synchronized(this) {
            for (int i = 0; i < 10; i++) {
                System.out.println("线程" + i);
            }
        }
    }
}

结果:在这里插入图片描述
当两个并发线程(thread和thread1)访问同一个对象(syncThread)中的synchronized代码块时,在同一时刻只能有一个线程得到执行,另一个线程受阻塞,必须等待当前线程执行完这个代码块以后才能执行该代码块。

当然,当一个线程访问对象的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该对象中的非synchronized(this)同步代码块

同步代码块范围是{}里

修饰一个方法

public class text11 {
    public static void main(String[] args) {
        textSynchThread sy = new textSynchThread();
        Thread thread = new Thread(sy);
        Thread thread1 = new Thread(sy);
        thread.start();
        thread1.start();

    }
}
class textSynchThread implements Runnable{
    @Override
    public synchronized void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println("线程" + i);
            }
    }
}

修饰方法范围是整个函数

5、线程通信

概述: 线程与线程之间不是相互独立的个体,它们彼此之间需要相互通信和协作

wait/notify 机制
wait()——让当前线程 (Thread.concurrentThread() 方法所返回的线程) 释放对象锁并进入等待(阻塞)状态。
notify()——唤醒一个正在等待相应对象锁的线程,使其进入就绪队列,以便在当前线程释放锁后竞争锁,进而得到CPU的执行。
notifyAll()——唤醒所有正在等待相应对象锁的线程,使它们进入就绪队列,以便在当前线程释放锁后竞争锁,进而得到CPU的执行。

public class text11 {
    public static void main(String[] args) {
    	Wait wait = new Wait();
        Notify notify = new Notify();
        wait.start();
        notify.start();
        }
}
class Wait extends Thread{
    @Override
    public void run() {
        synchronized (this){
                System.out.println("线程"+Thread.currentThread().getName());
                try {
                    System.out.println("wait并释放"+Thread.currentThread().getName());
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            System.out.println("完成");
        }
    }
}
class Notify extends Thread{
    @Override
    public void run() {
        synchronized (this){
            System.out.println("线程"+Thread.currentThread().getName());
            notify();
            System.out.println("线程唤醒"+Thread.currentThread().getName());
        }
        System.out.println("完成");
    }
}
6、线程池

线程池:线程容器,可设定线程分配的数量上限,将预先创建的线程对象存入池中,并重用线程池中的线程对象,避免频繁的创建和销毁

(回顾时补充···)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值