Concurrent programming, set framework

Uncle Ben's catalogue

ava concurrent programming

Why is it important

Concurrent programming can make full use of computer resources, maximize the performance of the computer, save the cost of the company and improve efficiency

1. What is high concurrency

The difference between concurrency and parallelism

Concurrent concurrency: multiple threads operate the same resource "at the same time", which is not really simultaneous operation, but alternating operation. In the case of single core CPU, resources are allocated to multiple threads according to time period (one processor handles multiple tasks)

Parallel parallelism: it is true that multiple threads execute at the same time, multi-core CPU, and each thread uses one CPU resource to run

Concurrent programming describes a design structure that allows the system to allow multiple tasks to be executed in overlapping time periods. It does not mean that multiple tasks are executed in the same time period, but that the system has the ability to process multiple tasks to be executed at the same time.

High concurrency means that the program we designed can support the execution of a large number of tasks in overlapping time periods.

High concurrency criteria:

  • QPS: the number of HTTP requests responded per second. QPS is not a concurrent number
  • Throughput: the number of requests processed per unit time, which is determined by QPS and concurrency
  • Average response time: the average time the system takes to respond to a request

QPS = concurrency / average response time

  • Number of concurrent users: the number of users carrying the system in normal use at the same time

Internet distributed architecture design, two ways to improve system concurrency:

  • Vertical expansion
  • Horizontal expansion

Vertical expansion

Improve stand-alone processing capacity (one computer)

  • 1. Upgrade the stand-alone hardware equipment, increase the number of CPU cores, upgrade the network card, expand the capacity of hard disk and upgrade the memory

  • 2. Improve the architecture performance of a single machine, use Cache to improve efficiency, use asynchronous requests to increase the throughput of a single service, and NoSQL to improve database access capability

Horizontal expansion

(multiple computers)

Cluster: one chef can't make it. Hire more chefs to cook together. Many people do the same thing.

Distributed: task segmentation, hire two assistants for the chef, one is responsible for washing vegetables, the other is responsible for cutting vegetables, and the chef is only responsible for cooking. A thing is divided into multiple steps and completed by different people.

Site layer extension: Nginx reverse proxy. If one Tomcat can't run, then 10 Tomcats will run

Service layer extension: RPC framework realizes remote call. Spring Cloud, Spring Boot, Dubbo and distributed architecture split business logic into different RPC clients to complete corresponding businesses. If a business has a large amount of concurrency, adding a new RPC Client can expand the performance of the service layer and achieve unlimited concurrency in theory

Expansion of data layer: in the case of a large amount of data, the original database server is divided into multiple servers, which has achieved the purpose of expanding the system performance, including master-slave replication, separation of reading and writing, separate tables and databases

2,JUC

JUC: import java.util.concurrent

A toolkit provided by JDK is specially used to help developers complete java Concurrent Programming

3. Processes and threads

The default number of threads in java is 2

  • Main main thread

  • GC garbage collection mechanism

    java itself cannot start threads. java cannot operate hardware. It can only call local methods and the dynamic function library written in C + +

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (IMG zoqsidfk-16336717401240) (C: \ users \ Deku \ appdata \ roaming \ typora \ typora user images \ image-20210727165619657. PNG)]

There are several ways to implement multithreading in java

1. Inherit Thread class

2. Implement Runnable interface

3. Implement Callable interface

The difference between Callable and Runnable is that the run method of Runnable has no return value, and the call method of Callable has a return value

public class CallAble01 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        testCallAble callAble = new testCallAble();
        FutureTask<String> futureTask = new FutureTask<>(callAble);
        new Thread(futureTask).start();
        String val = futureTask.get();
        System.out.println(val);
    }
}
class testCallAble implements Callable<String>{
    @Override
    public String call() throws Exception {
        System.out.println("Thread opened");
        return "helloWord";
    }
}
  • Callable is not directly related to Thread, and Thread cannot be directly started by Thread (new Thread(callable).start()),

    Because FutureTask is related to Runnable, you can use FutureTask to start threads

  • The following two are the two constructors of FutureTask

public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }
public FutureTask(Runnable runnable, V result) {
        this.callable = Executors.callable(runnable, result);
        this.state = NEW;       // ensure visibility of callable
    }

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-9blj6wp2-163367401242) (C: \ users \ Deku \ appdata \ roaming \ typora user images \ image-20210808154600828. PNG)]

  • Resources and threads are bound, and the coupling degree is too high
public class Callable02 {
    public static void main(String[] args) {
        Account account = new Account();
        new Thread(account,"A").start();
        new Thread(account,"B").start();


    }
}

class Account implements Runnable{
    private static int num=0;
    @Override
    public synchronized void run() {
        num++;
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"Is the current second "+num+"Bit accessed");
    }
}
  • decoupling
public class Callable03 {
    public static void main(String[] args) {
        Account01 account = new Account01();
        new Thread(()->{
            account.count();
        },"A").start();
        new Thread(()->{
            account.count();
        },"B").start();
    }	
}
class  Account01{
    private static int num=0;
    public synchronized void count() {
        num++;
        System.out.println(Thread.currentThread().getName()+"Is the current second "+num+"Bit accessed");
    }
}

4. Sleep and Wait

  • The difference between sleep and wait is that the two methods come from different classes, namely Thread and Object

  • Sleep is to sleep the current thread, and wait is to sleep the thread accessing the current object.

  • sleep will not release the lock, but wait will release the lock

  • sleep handles threads and wait handles resources

  • Since the thread waiting for a lock can resume operation only after obtaining the lock, it is very important to let the thread holding the lock release the lock in time when it does not need the lock. The thread holding the lock releases the lock when:

    1. The synchronization method and code block of the current thread are released at the end of execution

    2. When the current thread encounters a break or return in the synchronized method or synchronized code block, it is released when the code block or method is finally released.

    3. It is released when the current thread has an unhandled error or exception leading to an abnormal end

    4. Calling obj.wait() will immediately release the lock, and the current thread will pause and release the lock so that other threads can execute obj.notify(), but notify() will not immediately release the obj lock in sycronized(obj). The lock will not be released until the thread where notify() is located executes all the code in the synchronized(obj) block. While yield(),sleep() does not release the lock.

5. What is synchronized locked

1. When synchronized modifies a non static method, the caller of the method is locked

public class Callable04 {
    public static void main(String[] args) {
        Date date = new Date();
        new Thread(()->{date.func1();},"AAA").start();
        new Thread(()->{date.func2();},"BBB").start();
    }
}
class Date{
    public synchronized void func1() {
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("I'm number one");
    }
    public synchronized void func2(){
     
        System.out.println("I'm second");
    }
}
/*Own understanding
1-Before locking, AAA waits for five seconds before entering the method, and BBB waits for three seconds, so BBB outputs first
 I'm second
 I'm number one
2-After locking, synchronized locks the caller of the method, that is, the date from new,
AAA Go first and wait for five seconds. Because date is locked, BBB can only wait for AAA to finish before entering
 I'm number one
 I'm second
*/

2. When synchronized modifies a static method, it locks the class

public class Callable04 {
    public static void main(String[] args) {
        Date date = new Date();
        Date date2 = new Date();
        new Thread(()->{date.func1();},"AAA").start();
        new Thread(()->{date2.func2();},"BBB").start();
    }
}
class  Date{
    public synchronized static void func1() {
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("I'm number one");
    }
    public synchronized static void func2(){
        System.out.println("I'm second");
    }
}
/*
Because synchronized modifies a static method to lock a class, when thread AAA enters func1, class Data() is locked,
So thread BBB has to wait,
I'm number one
 I'm second
*/

3. synchronized static methods and instance methods exist at the same time. Static methods lock classes and instance methods lock objects

public class Callable04 {
    public static void main(String[] args) {
        Date date = new Date();
//        Date date2 = new Date();
        new Thread(()->{date.func1();},"AAA").start();
        new Thread(()->{date.func2();},"BBB").start();
    }
}
class  Date{
    public synchronized static void func1() {
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("I'm number one");
    }
    public synchronized void func2(){
        System.out.println("I'm second");
    }
}
/*
Because func1 is a static method, which locks classes, and func2 is an instance method, which locks instance objects,
They manage their own and can't synchronize
*/

6,lock

  • A locking mechanism provided by JUC has similar functions to synchronized. It is an upgrade of synchronized. It is an interface

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-ntoolrj-1633617401243) (C: \ users \ Deku \ appdata \ roaming \ typora user images \ image-20210808210609854. PNG)]

  • Lock its implementation class

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-nwezteii-163367401244) (C: \ users \ Deku \ appdata \ roaming \ typora user images \ image-20210808210804354. PNG)]

  • His common implementation class is ReentrantLock

  • synchronized implements the locking mechanism through JVM, and ReentrantLock implements the locking mechanism through JDK

  • synchronized is a keyword and ReentrantLock is a class, which is essentially different

  • ReentrantLock is called reentrant lock in Chinese. As its name implies, multiple locks can be added to the same resource

  • Different unlocking methods:

    • synchronized: automatically releases the lock after the thread is executed,
    • ReentrantLock: manual unlocking is required

Classic case ticket selling

  • synchronized lock for ticket selling
//Selling tickets
public class lock01 {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        new Thread(()->{
            for (int i = 0; i < 3000; i++) {
                ticket.sale();
            }},"Zhang San").start();
        new Thread(()->{
            for (int i = 0; i <3000 ; i++) {
                ticket.sale();
            }},"Li Si").start();
    }
}
class Ticket{
    private Integer saleNum=0;//Sell tickets
    private Integer lastNum=3000;//Remaining tickets
    public synchronized void sale(){
        if(lastNum>0){
            saleNum++;
            lastNum--;
            try {
                TimeUnit.MILLISECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName()+"Sold"+saleNum+"Tickets, remaining"+lastNum);
        }
        System.out.println("-=---");
    }
}
  • Ticket Locked lock
 //Selling tickets
public class lock01 {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        new Thread(()->{
            for (int i = 0; i < 3000; i++) {
                ticket.sale();
            }},"Zhang San").start();
        new Thread(()->{
            for (int i = 0; i <3000 ; i++) {
                ticket.sale();
            }},"Li Si").start();
    }
}
class Ticket{
    private Integer saleNum=0;//Sell tickets
    private Integer lastNum=3000;//Remaining tickets
    private Lock lock=new ReentrantLock();
    public  void sale(){
        lock.lock();
        if(lastNum>0){
            saleNum++;
            lastNum--;
            try {
                TimeUnit.MILLISECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName()+"Sold"+saleNum+"Tickets, remaining"+lastNum);
        }
        lock.unlock();
        System.out.println("-=---");
    }
}
/*
Of course, we can lock more than one lock, but we should pay attention to unlocking several times
*/

The difference between synchronized and Lock locks

1. synchronized is automatically locked and unlocked. Lock lock is manual locking and manual unlocking

2. synchronized is unable to determine whether a lock has been obtained. Lock can determine whether a lock has been obtained

3. synchronized will wait all the time if you can't get the lock. Lock doesn't necessarily wait all the time (tryLock is described below)

4. synchronized is the keyword and Lock is the interface

5. synchronized is a non fair lock. Lock can set whether it is a fair lock

private Lock lock=new ReentrantLock(true);

Fair lock: fair and queued. When the lock is not occupied, the current thread needs to judge whether there are other waiting threads in the queue

Unfair lock: unfair, queue jumping. When the lock is not occupied, the current thread can directly occupy it without judging whether there are waiting threads in the queue

Lock lock is recommended in actual development

  • ReentrantLock is time limited. It can judge whether a thread can obtain a lock within a certain period of time. Using the tryLock method, it returns a Boolean type. true indicates that the lock can be obtained, and false indicates that the lock cannot be obtained
public class lock02 {
    public static void main(String[] args) {
        TimeOut timeOut = new TimeOut();
        new Thread(()->{timeOut.timeLock();},"A").start();
        new Thread(()->{timeOut.timeLock();},"B").start();
    }
}
class TimeOut{
    private ReentrantLock lock=new ReentrantLock();
    public void timeLock(){
        try {
            if(lock.tryLock(3, TimeUnit.SECONDS)){//Judge whether you can get the lock in three seconds
                System.out.println(Thread.currentThread().getName()+"Got the lock");
                TimeUnit.SECONDS.sleep(5);
            }else{
                System.out.println(Thread.currentThread().getName()+"I didn't get the lock");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if(lock.isHeldByCurrentThread()){//Determine whether the current thread holds this lock,
                lock.unlock();
            }
        }
    }
}
/*
lock.isHeldByCurrentThread()This method is the method in ReentrantLock, not the method in Lock
 This method indicates whether the current thread holds the lock
*/

Producer consumer model

synchronized

public class lock03 {
    public static void main(String[] args) {
        Data data = new Data();
        new Thread(()->{
            for (int i = 0; i <10 ; i++) {
                data.producers();
            }},"A").start();
        new Thread(()->{
            for (int i = 0; i <10 ; i++) {
                data.consumers();
            }},"B").start();
    }
}
class Data{
    private Integer num=0;
    public synchronized void producers(){
        while(num!=0){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        num++;
        this.notify();
        System.out.println(Thread.currentThread().getName()+"Produced:"+num+"Chicken");
    }
    public synchronized void consumers(){
        while(num==0){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }System.out.println(Thread.currentThread().getName()+"Consumed:"+num+"Chicken");
        num--;
        this.notify();
    }
}
  • You must use while to judge, not if, because if will cause false wake-up of threads. False wake-up means that some wait methods will be awakened except notify, not really.

Because if will be executed only once, the execution will be followed by the execution down to the outside of if ()
While does not, it will not execute the operation outside while () until the conditions are met

Lock

public class lock03 {
    public static void main(String[] args) {
        Data data = new Data();
        new Thread(()->{
            for (int i = 0; i <10 ; i++) {
                data.producers();
            }},"A").start();
        new Thread(()->{
            for (int i = 0; i <10 ; i++) {
                data.consumers();
            }},"B").start();
    }
}
class Data{
    private Integer num=0;
    private ReentrantLock lock=new ReentrantLock();
    private Condition condition=lock.newCondition();
    public void producers(){
        lock.lock();
        while(num!=0){
            try {
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        num++;
        condition.signal();
        System.out.println(Thread.currentThread().getName()+"Produced:"+num+"Chicken");
        if(lock.isHeldByCurrentThread()){lock.unlock();}
    }
    public synchronized void consumers(){
        lock.lock();
        while(num==0){
            try {
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName()+"Consumed:"+num+"Chicken");
        num--;
        condition.signal();
        if(lock.isHeldByCurrentThread()){lock.unlock();}
    }
}
  • With Lock lock, you can't use wait and notify to pause and wake up threads. Instead, you should use await and signal of Condition to pause and wake up threads.

7,ConcurrentModificationException

Concurrent access exception (if there is no separation between reading and writing, an exception will be reported while reading and writing)

public class lock04 {
    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            new Thread(()->{
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //write
                list.add("a");
                //read
                System.out.println(Thread.currentThread().getName()+list);
                //Read / write a resource and report the exception at the same time
            },String.valueOf(i)).start();
        }
    }
}
/*
Modify a resource at the same time
 We can see that ArrayList is thread unsafe
*/

How to solve it?

1. Change a resource and replace the ArrayList with a Vector

Vector list = new Vector<>();

The add method of Vector has the synchronized keyword

x [the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-lmclo5ui-16336717401245) (C: \ users \ Deku \ appdata \ roaming \ typora \ user images \ image-20210809163211967. PNG)]

ArrayList is not synchronized, so its thread is unsafe

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-jjpcy567-163367401246) (C: \ users \ Deku \ appdata \ roaming \ typora user images \ image-20210809163527194. PNG)]

2. Use Collections.synchronizedList()

List<String> list= Collections.synchronizedList(new ArrayList<>());

This is a processing of ArrayList

3. JUC: CopyOnWriteArrayList (read write separation)

List<String> list = new CopyOnWriteArrayList();
  • // Source code of add method in CopyOnWriteArrayList
    public boolean add(E e) {
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] elements = getArray();//Copy the original array and put it in elements
                int len = elements.length;
                Object[] newElements = Arrays.copyOf(elements, len + 1);//Define a new array, put elements in it, and count 																		 Group length plus 1 (to put e)
                newElements[len] = e;//Put the contents of add into the new array
                setArray(newElements);//Replace the new array with the original array (set)
                return true;
            } finally {
                lock.unlock();
            }
        }
    
  • set

public class lock04 {
    public static void main(String[] args) {
//        Vector<String> list = new Vector<>();
//        List<String> list= Collections.synchronizedList(new ArrayList<>());
        Set<String> list = new CopyOnWriteArraySet<>();
        for (int i = 0; i < 20; i++) {
            final int temp=i;
            new Thread(()->{
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //write
                list.add(String.valueOf(temp)+"a");
                //read
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
}
  • Map
public class lock04 {
    public static void main(String[] args) {
//        Vector<String> list = new Vector<>();
//        List<String> list= Collections.synchronizedList(new ArrayList<>());
        Map<String,Object> map = new ConcurrentHashMap<>();
        for (int i = 0; i < 10; i++) {
            final int temp=i;
            new Thread(()->{
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
             map.put(UUID.randomUUID().toString().substring(0,3),UUID.randomUUID().toString().substring(0,2));
                System.out.println(map);
            },String.valueOf(i)).start();
        }
    }
}
/*
UUID.randomUUID().toString().substring(0,3)
Generate a random number and take the first two digits.
*/

8. JUC tool class

  • CountDownLatch: subtraction counter

    • It can be used to count down. When two threads execute at the same time, if you want to ensure that one thread executes first, you can use the counter. When the counter is cleared, let another thread execute

    • new CountDownLatch(100), countDownLatch.countDown(), countDownLatch.await() must be used together. Count down() must be executed as many times as the value assigned during creation. Otherwise, the counter will not stop and other threads will not wake up. Therefore, it must be ensured that the counter is cleared and countDown() The number of calls must be greater than the parameter value of the constructor

public class JUC01 {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(100);
        new Thread(()->{
            for (int i = 0; i < 100; i++) {
                System.out.println("Thread thread ++++++++++++++");
                countDownLatch.countDown();
            }
        }).start();
                countDownLatch.await();
        for (int i = 0; i < 100; i++) {
            System.out.println("main thread +++++++++++");
        }
    }
}
/*
CountDownLatch.await() Method blocks the current thread before the countdown is 0. The counter stops and wakes up other threads
*/
  • CyclicBarrier: addition counter

cyclicBarrier.await(); Try to wake up the counter thread in other threads. When the execution times of other threads reach the critical value of the counter, the counter thread will be awakened, and the counter can be reused. When the execution of the counter thread is completed once, the counter will be automatically cleared to wait for the next execution

public class JUC02 {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(20,()->{
            System.out.println("Release-----------");
        });//When the thread executes 30 times, it outputs once
        for (int i = 0; i < 100; i++) {
            final int temp=i;
            new Thread(()->{
                try {
                    cyclicBarrier.await();
                    System.out.println(temp);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}
/*
final int temp=i;The function of temp here is because the variables in lambda must be final or valid final
*/
  • Semaphore: count semaphores

In the actual development, it is mainly used to complete the flow limiting operation and limit the number of threads that can access some resources

There are only three operations with Semaphore

1. Initialization

2. Obtaining permits

3. Release

When each thread executes, it first needs to obtain the semaphore. It can execute only after obtaining the resources. After execution, it needs to release the resources for the next thread.

public class JUC03 {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(5,true);//Initialization. The truth table is that it is a fair lock and can't jump the queue
        for (int i = 0; i < 20; i++) {
            new Thread(()->{
                try {
                    semaphore.acquire();//Get permission
                    System.out.println(Thread.currentThread().getName()+"Go shopping");
                    TimeUnit.SECONDS.sleep(5);
                    System.out.println(Thread.currentThread().getName()+"Go out");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release();//release
                }
            },String.valueOf(i)).start();
        }
    }
}

9. Read write lock

It is an interface ReadWriteLock, and the implementation class is ReentrantReadWriteLock. It can be read by multiple threads at the same time, but only one thread can write at the same time.

Read / write locks are also used to achieve thread synchronization, but the granularity is finer. Different locks can be set for read and write operations respectively

A write lock is also called an exclusive lock, which can only be occupied by one thread. A read lock is also called a shared lock, which is occupied by multiple threads at the same time.

public class JUC04 {
    public static void main(String[] args) {
        ReadWrite readWrite = new ReadWrite();
        for (int i = 0; i < 5; i++) {
            final int temp=i;
            new Thread(()->{
                readWrite.write(temp,String.valueOf(temp));
            },String.valueOf(i)).start();
        }
        for (int i = 0; i < 5; i++) {
            final int temp=i;
            new Thread(()->{
                readWrite.read(temp);
            },String.valueOf(i)).start();
        }
    }
}
class ReadWrite{
    private HashMap<Integer,String> map=new HashMap<>();
    private ReadWriteLock readWriteLock=new ReentrantReadWriteLock();
    public void write(Integer key,String value){
        /*
        * write in
        * */
        readWriteLock.writeLock().lock();
        System.out.println(key+"Start writing");
        map.put(key, value);
        System.out.println(key+"Write complete");
        readWriteLock.writeLock().unlock();
    }
    public void read(Integer key){
        /*
        * read
        * */
        readWriteLock.readLock().lock();
        System.out.println(key+"Start reading");
        map.get(key);
        System.out.println(key+"Read complete");
        readWriteLock.readLock().unlock();
    }
}

10. Thread pool

A certain number of Thread objects are created in advance and stored in the buffer pool. When necessary, they are directly taken out of the buffer. After they are used up, they are not destroyed. They are returned to the buffer pool. In order to improve the utilization of resources - the idea of pooling

advantage

  • Improve thread utilization
  • Improve response speed
  • Facilitate the same management thread object
  • The maximum number of concurrent can be controlled

1. A certain number of Thread objects are created during thread pool initialization

2. If there is no idle thread object in the buffer pool, the new task enters the waiting queue

3. If there are no idle thread objects in the buffer pool and the waiting queue is full, you can apply to create a certain number of new thread objects until the maximum value of the thread pool is reached. At this time, if there are new tasks coming in, you can only choose to refuse

//Tool classes are not recommended for actual development
public class pool01 {
    public static void main(String[] args) {
        //Singleton - open only one thread
//        ExecutorService executorService= Executors.newSingleThreadExecutor();
        //Specifies the number of threads
//        ExecutorService executorService=Executors.newFixedThreadPool(5);
        //Cache thread pool, number of threads opened (Integer.MAX_VALUE)
        ExecutorService executorService=Executors.newCachedThreadPool();
        for (int i = 0; i < 1000; i++) {
            final int temp =i;
            executorService.execute(()->{
                System.out.println(Thread.currentThread().getName()+"----"+temp);
            });
        }
        executorService.shutdown();
    }
}
/*
newSingleThreadExecutor
newFixedThreadPool
newCachedThreadPool
 These three tool classes are implemented through new ThreadPoolExecutor, so we should define them through new ThreadPoolExecutor in actual development,
*/

No matter what kind of thread pool is encapsulated by the tool class Executor, the underlying code is the same. The thread pool is built by creating a ThreadPoolExecutor object

  • ThreadPoolExecutor source code
    public ThreadPoolExecutor(int corePoolSize, //Core pool size, number of initialized threads
                              int maximumPoolSize,//The maximum number of threads in the thread pool, which determines the upper limit of the thread pool
                              long keepAliveTime,//survival time 
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
  • corePoolSize: core pool size, number of initialized threads

  • maximumPoolSize: the maximum number of threads in the thread pool. It determines the upper limit of the thread pool

corePoolSize is the size of the thread pool. maximumPoolSize is a remedial measure when the number of tasks increases suddenly.

  • keepaliveTime: the lifetime of the thread object

  • Unit: thread object lifetime unit

  • workQueue: wait queue

  • threadFactory: thread factory, used to create thread objects

  • handler: reject policy (four types)

    • AbortPolicy: throw an exception directly

      • java.util.concurrent.RejectedExecutionException
    • DiscardPolicy: discard the task without throwing an exception

    • DiscardOldestPolicy: try to compete with the top task in the waiting queue without throwing exceptions

    • CallerRunsPolicy: who calls and who handles

      • main=====>Handle business 5
        pool-1-thread-3=====>Handle business 4
        pool-1-thread-2=====>Handle business 1
        pool-1-thread-1=====>Handle business 0
        pool-1-thread-3=====>Handle business 2
        pool-1-thread-1=====>Handle business 3
        

Custom thread pool

//Custom thread pool
public class pool02 {
    public static void main(String[] args) {
        ExecutorService executorService=null;
        try {
            //Custom thread pool parameters
            executorService=new ThreadPoolExecutor(
                    2,
                    3,
                    1L,
                    TimeUnit.SECONDS,
                    new ArrayBlockingQueue<>(2),
                    Executors.defaultThreadFactory(),
                    new ThreadPoolExecutor.AbortPolicy());
            for (int i = 0; i < 6; i++) {
                final int temp=i;
                executorService.execute(()->{
                    try {
                        TimeUnit.MILLISECONDS.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"=====>Handle the business"+temp);
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
           executorService.shutdown();
        }
    }
}
/*
i=1,2,It means that 1 or 2 people handle business, meet the size of the core pool, and start the core thread according to the size of i
i=3,4,It means that 3 or 4 people come to handle business. The core pool is full and enters the queue
i=5. It means that five people come to handle business. The core pool is full and the queue is full. Only remedial measures can be started and another thread can be started
i=6.It means that 6 people are handling business. The core pool is full and the queue is full, and it exceeds the upper limit of the thread pool, so the rejection policy can only be used
 The sixth person can only be shut out
*/

Three test sites of thread pool

1. Three implementations of Executors tool class

//Singleton - open only one thread
ExecutorService executorService= Executors.newSingleThreadExecutor();
//Specifies the number of threads
ExecutorService executorService=Executors.newFixedThreadPool(5);
//Cache thread pool, number of threads opened (Integer.MAX_VALUE)
ExecutorService executorService=Executors.newCachedThreadPool();

2. Seven parameters

int corePoolSize, //Core pool size, number of initialized threads
int maximumPoolSize,//The maximum number of threads in the thread pool, which determines the upper limit of the thread pool
long keepAliveTime,//survival time 
TimeUnit unit,//Thread object lifetime unit
BlockingQueue<Runnable> workQueue,//Waiting queue
ThreadFactory threadFactory,//Thread factory, used to create thread objects
RejectedExecutionHandler handler//Reject policy

3. Four rejection strategies

- AbortPolicy:  //Throw an exception directly
- DiscardPolicy: //Abandon the task without throwing an exception
- DiscardOldestPolicy: //Try to compete with the top task in the waiting queue without throwing exceptions
- CallerRunsPolicy: //Who calls, who handles

11. ForkJoin framework

ForkJoin is a multithreaded concurrent processing framework released after JDK=1.7. Its function is similar to that of JUC. JUC often uses a single class to complete operations. ForkJoin uses multiple classes to complete a certain work at the same time, which is richer in processing than JUC. There are not many scenarios used in actual development. It will be used only when Internet companies really have high concurrent requirements, and points will be added in the interview

It is essentially a supplement to the thread pool and an extension of the function of the thread pool. Based on the thread pool, its core idea is to split a large task into many small tasks and execute them respectively. Finally, the results of small tasks are summarized to generate the final results

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-afmav3gx-163367401247) (C: \ users \ Deku \ appdata \ roaming \ typora user images \ image-20210810204734894. PNG)]

The essence is to split the task of a thread into multiple small tasks, then multiple tasks are executed concurrently, and finally the results are summarized.

For example, two threads a and B execute at the same time. A has more tasks and B has fewer tasks. B completes the task first. At this time, B helps a complete the task (take part of a to execute for a and summarize the results after execution), so as to improve efficiency. This is work stealing

work stealing

ThreadPoolExecutor the thread pool itself will not steal work (help each other). ForkJoin in order to improve efficiency,

The core of ForkJoin framework is two classes

  • ForkJoinTask split task
  • ForkJoinPool provides multithreaded concurrent work stealing.

The most important thing to use ForkJoinTask is to figure out how to split the task. The idea of recursion is used here.

1. ForkJoinTask task needs to be created. ForkJoinTask is an abstract class and cannot directly create an instance object of ForkJoinTask. We need to customize a class and inherit the ForkJoinTask subclass RecursiveTask. Recursive means recursion. This class provides the function of recursion

/*
10 Sum of billion
*/
public class ForkJoinTask01 extends RecursiveTask<Long> {
    private Long start;
    private Long end;
    private Long temp=100_0000L;

    public ForkJoinTask01(Long start, Long end) {
        this.start = start;
        this.end = end;
    }
    @Override
    protected Long compute() {
        if(end-start<temp){
            Long sum=0L;
            for (Long i = start; i <= end; i++) {
                    sum+=i;
            }
            return sum;
        }else{
            Long avg=(start+end)/2;
            ForkJoinTask01 Task1 = new ForkJoinTask01(start,avg);
            Task1.fork();
            ForkJoinTask01 Task2 = new ForkJoinTask01(avg+1,end);
            Task2.fork();
            return Task1.join()+Task2.join();
        }
    }
}
public class Test {
    public static void main(String[] args) {
        long StartTimeMillis = System.currentTimeMillis();
        ForkJoinPool joinPool = new ForkJoinPool();
        ForkJoinTask01 task = new ForkJoinTask01(0L,10_0000_0000L);
        joinPool.execute(task);
        Long sun=0L;
        try {
            sun=task.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        long endTimeMillis = System.currentTimeMillis();
        System.out.println(sun+"Yes"+(endTimeMillis-StartTimeMillis));
        joinPool.shutdown();
    }
}

12. Volatile keyword

public class text01 {
    public static void main(String[] args) {
        List<String> list= new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                list.add("a");//There are collections with the same output length because threads have opened up memory space
                System.out.println(list);
            }).start();
        }
    }
}

Volatile is a lightweight synchronization mechanism provided by the JVM. It is visible to the main memory object thread (understand what the main memory object thread is visible)

  • What is memory visibility
  • [the external chain image transfer fails, and the source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-zpsd8pse-163367401248) (C: \ users \ Deku \ appdata \ roaming \ typora \ user images \ image-20210811160413115. PNG)]
public class text02 {
    private static int num=0;
    public static void main(String[] args) {
        new Thread(()->{
            while (num==0){
            }
        }).start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        num=1;
        System.out.println(num);

    }
}
/*
The thread copies a copy from the shared variable to the working memory
 From the above code, we can see that when num=0, the thread enters the where loop, but when we assign a value to num again and restart, the thread is still in the loop after the program outputs 1, which shows the visibility of memory. At the beginning, the thread gets the value from the shared variable and copies it to the working memory to enter the loop. When num=1, Our main thread copies the value of num and assigns num to 1. Therefore, the secondary thread does not exit the loop
*/

The function of Volatile is to jump the working memory and turn it into visibility. The main memory object thread is visible,

private static volatile int num=0;

Think about a question? If I don't use Volatile and I output it in where, will the thread stop?

while (num==0){
                System.out.println("---");
            }
  • Generally speaking, the thread will always loop out "-" and will not exit the loop, but we found that it will exit the loop after operation???

    Why can't he perceive the change of num if there is no output in the loop? If there is a task in the loop, he can perceive the change of num

  • Because after a thread executes a task, it will save the variable back to main memory and read the latest value of the current variable from memory. If it is an empty task, it will not re read the value in memory

workQueue in thread pool

A blocking queue is used to execute the queue waiting for the specified. The commonly used blocking queues are as follows:

  • ArrayBlockingQueue: array based first in first out queue. The size must be specified when creating.
  • LinkBlockingQueue: a linked list based first in first out queue. It can be created without specifying the size. The default value is Integer.MAX_VALUE
  • Synchronous queue: instead of saving the submitted task, it directly creates a new thread to execute the new task.
  • PriorityBlockQueue: it is a blocking pair column with priority

Collection framework

Why use a collection framework?

1. The length of the array is fixed

2. An array cannot store multiple different data types at the same time

A collection is simply understood as a dynamic array whose length can be changed and can maintain any data type.

Set itself is one of the basic concepts of data structure. What we say here is the java language, which is the concrete implementation of this data structure.

The collection in java is not completed by a class, but a framework system composed of a group of interfaces and classes. It can be roughly divided into three layers. The top layer is a group of interfaces, followed by the implementation class of the interface.

Interface

  • Collection: the most basic and top-level interface of the collection framework
  • List: the sub interface of Collection. It is an ordered, non unique object and the most commonly used interface
  • Set: the sub interface of Collection. It is an unordered and unique object
  • Map: another interface independent of Collection, the top-level interface, stores a group of key value objects and provides key to value mapping
  • Iterator: interface for outputting collection elements, generally used for unordered interfaces
  • ListIterator: Iterator sub interface, which can output elements in a collection in both directions
  • Enumeration: the traditional output interface has been replaced by Iterator
  • SortedSet: the sub interface of Set, which can sort the elements in the Set
  • SortedMap: the sub interface of Map, which can sort the elements in the collection
  • Queue: queue interface.
  • Map. Entry: the internal interface of map, which describes a set of key value pair elements stored in map

1. Collection interface

/* 
 *@see     Set
 * @see     List
 * @see     Map
 * @see     SortedSet
 * @see     SortedMap
 * @see     HashSet
 * @see     TreeSet
 * @see     ArrayList
 * @see     LinkedList
 * @see     Vector
 * @see     Collections
 * @see     Arrays
 * @see     AbstractCollection
 * @since 1.2
 */

public interface Collection<E> extends Iterable<E> {
    // Query Operations
  • The Iterable interface is the top-level interface, which implements the output of the collection

Collection is the most basic parent interface in the collection framework. It can store a group of unordered and non unique objects. Generally, it is not directly used or instantiated, but only used to provide specifications.

Collection is a sub interface of Iterable interface.

  • int size();                         //Get collection length
    
  • boolean isEmpty();                  //Determine whether the collection is empty
    
  • boolean contains(Object o);         //Judge whether an object exists in the collection, including
    
  • Iterator<E> iterator();             //Instantiate the Iterator interface to traverse the collection
    
  • Object[] toArray();                 //Converts a collection to an array
    
  • <T> T[] toArray(T[] a);             //Converts the collection to an array of the specified data type
    
  • boolean add(E e);                   //Add elements to the collection
    
  • boolean remove(Object o);           //Remove element from collection
    
  • boolean containsAll(Collection<?> c);//Determines whether all elements in another collection exist in the collection
    
  • boolean addAll(Collection<? extends E> //Adds all elements in a collection to the collection
    
  • boolean removeAll(Collection<?> c);    //Removes all elements of an element from the collection
    
  • void clear();                          //Clears all elements in the collection
    
  • boolean equals(Object o);              //Judge whether two sets are equal
    
  • int hashCode();                        //Returns the hash value of the collection
    

2. Collection sub interface

  • List: used to store ordered, non unique elements
  • Set: store unordered and unique elements
  • Queue: queue interface

3. List interface

 /*
 * @see Collection
 * @see Set
 * @see ArrayList
 * @see LinkedList
 * @see Vector
 * @see Arrays#asList(Object[])
 * @see Collections#nCopies(int, Object)
 * @see Collections#EMPTY_LIST
 * @see AbstractList
 * @see AbstractSequentialList
 * @since 1.2
 */

public interface List<E> extends Collection<E> {
    // Query Operations 

In addition to inheriting the method of Collection

List common extension methods

  • E get(int index);                //Returns the element at the corresponding position in the collection by subscript
    
  • E set(int index, E element);     //Stores an object at a specified location in the collection
    
  • int indexOf(Object o);           //Find the position of an object in the collection from front to back
    
  • int lastIndexOf(Object o);       //Find the position of an object in the collection from back to front
    
  • ListIterator<E> listIterator();  //Instantiate the Iterator interface to traverse the collection
    
  • List<E> subList(int fromIndex, int toIndex); //Intercepting the List set by subscript 
    

4. Implementation class of List interface

  • ArrayList: it is the most frequently used List implementation class in development. It implements arrays with variable length and allocates continuous space in memory, so it is fast to read and slow to add and delete

    • Non thread safe.
  • Vector: thread safety, low efficiency, thread safety is realized directly through the synchronized keyword

list.add(1,"Hello 1 ");   //Add a data at the position of 1
list.set(1,"Hello");     //Replace the value at position 1
  • Stack: a subclass of Vector, which implements the data structure of the stack (first in and last out)
public class Collection02 {
    public static void main(String[] args) {
        Stack<String> stack=new Stack<>();
        String push = stack.push("1");//Push 
        System.out.println(push);//The output is 1
        stack.add("2");//add is a method that inherits Vector and outputs a Boolean value
        stack.push("3");
        System.out.println("Stack top element"+stack.peek());
        System.out.println(stack);
        System.out.println("Stack top element"+stack.pop());
        System.out.println(stack);
        System.out.println(stack.search("1"));
    }
}

/*
peek():Copy the top element from the stack and output it
pop():Take the top element directly from the stack
 Output:
Stack top element 3
[1, 2, 3]
Stack top element 3
[1, 2]
*/

Let's take a look at the source code of the stack.search method: it uses the lastIndexOf method of List to find the location of elements from back to front

public synchronized int search(Object o) {
        int i = lastIndexOf(o);

        if (i >= 0) {
            return size() - i;
        }
        return -1;
    }
  • LinkedList: realize the first in first out queue and store it in the form of linked list.

The difference between ArrayList and LinkedList: the storage form in memory is different. ArrayList adopts the form of array and LinkedList adopts the form of linked list

The storage space of array in memory is continuous, fast to read and slow to add and delete.

Because the array is continuous in memory, the memory address of the target element can be quickly obtained according to the addressing formula (address=0000+4*n). Also, because the memory is continuous, adding or deleting elements must move the data, and the longer the array length, the more elements to move, and the slower the operation

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-6auqdy8q-163367401249) (C: \ users \ Deku \ appdata \ roaming \ typora \ user images \ image-20210812143701639. PNG)]

The linked list is discontinuous in memory, slow to read and fast to add and delete. The linked list is discontinuous in memory. There is no fixed formula to use. To read, you can only start from the first bit and traverse to the target element. The larger the data scale, the slower the operation.

Adding and deleting is fast, because you only need to reset the post pointers of the two nodes before and after the target element, which is independent of the data size

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-smz59u5l-163367401249) (C: \ users \ Deku \ appdata \ roaming \ typora user images \ image-20210812144733094. PNG)]

public class Collection03 {
    public static void main(String[] args) {
        LinkedList<String> linkedList = new LinkedList<>();
        linkedList.add("1");
        linkedList.add("2");
        linkedList.offer("3");
        System.out.println(linkedList);//[1, 2, 3]
        linkedList.push("4");//Added to the head of the linked list
        System.out.println(linkedList);//[4, 1, 2, 3]
        linkedList.addFirst("5");
        System.out.println(linkedList);//[5, 4, 1, 2, 3]
        linkedList.addLast("7");
        System.out.println(linkedList);//[5, 4, 1, 2, 3, 7]
        System.out.println(linkedList.peek());//5
        System.out.println(linkedList.peekFirst());//5
        System.out.println(linkedList.peekLast());//7
        System.out.println(linkedList.pop());//5
        System.out.println(linkedList);//[4, 1, 2, 3, 7]

    }
}

Think about a question??

  • LinkedList and Stack both have pop() methods. What are their differences and similarities??

    pop(): both methods take out the first element in the set, but the order of the two is opposite. Stack is "last in first out", so pop takes out the last element and LinkedList is "first in first out", so pop takes out the first element.

    LinkedList implements the Deque interface, and Deque is the sub interface of queue. Queue is the queue. The bottom layer implements the data structure of the queue

    In actual development, the Queue object cannot be instantiated directly.

    The implementation class of Queue is AbstractQueue, which is an abstract class and cannot be instantiated directly. Its subclass PriorityQueue needs to be used in development

    The data added in the Queue must be sequential.

public class Collection04 {
    public static void main(String[] args) {
        PriorityQueue<Object> priorityQueue = new PriorityQueue<>();
//        priorityQueue.add("1");
//        priorityQueue.add("2");
//        priorityQueue.add("A");
//        priorityQueue.add("B");
//        priorityQueue.comparator();
        priorityQueue.add(new A(1));
        priorityQueue.add(new A(2));
        System.out.println(priorityQueue);
    }
}
class A implements Comparable{
    private int num;
    public A(int num){
        this.num= num;
    }

    @Override
    public String toString() {
        return "A{" +
                "num=" + num +
                '}';
    }   

    @Override//compareTo comparison
    public int compareTo(Object o) {
        A a=(A)o;
        if (this.num>a.num) {
            return 1;
        }else if (this.num==num){
            return 2;
        }else {
            return -1;
        }
    }
}

Queue defaults to ascending and natural sorting of elements

5. Set interface

Like List, Set is the sub interface of Collection. The Set interface stores data in the form of hash, so the elements are out of order and can store a group of unordered and unique data

 /*
 * @see Collection
 * @see List
 * @see SortedSet
 * @see HashSet
 * @see TreeSet
 * @see AbstractSet
 * @see Collections#singleton(java.lang.Object)
 * @see Collections#EMPTY_SET
 * @since 1.2
 */

public interface Set<E> extends Collection<E> {
    // Query Operations

Set common implementation classes:

  • HashSet
  • LinkedHashSet
  • TreeSet

HashSet: it is an implementation class that we often use in our development. It stores a group of unordered and unique objects.

Unordered: the storage order of elements is different from that of convenience.

public class Collection05 {
    public static void main(String[] args) {
        HashSet<Object> hashSet=new HashSet<>();
        hashSet.add("C");
        hashSet.add("A");
        hashSet.add("B");
        System.out.println(hashSet);//[A, B, C]
        hashSet.remove("B");
    }
}

LinkedHashSet is another implementation class of Set, which can store an ordered and unique Set of elements

Order: the storage order of elements is consistent with the convenient order

public class Collection {
    public static void main(String[] args) {
        LinkedHashSet<Object> set=new LinkedHashSet<>();
        set.add("b");
        set.add("a");
        set.add("c");
        System.out.println(set);//[b, a, c]
        set.spliterator().forEachRemaining((n)->{
            System.out.println(n);//b a c
        });
    }
}
  • Think about the difference between equals and =???

Equals in all classes inherit the Object class. The native equals method in Object is judged by = =

 /*
 * @see     java.util.HashMap
 */
public boolean equals(Object obj) {
    return (this == obj);
}

However, each class can override the equals method, override the previous = = to make a logical judgment, and use the new logic to judge whether it is equal.

How does the LinkedHashSet determine whether two objects are equal?

First, it will judge whether the hashcodes of the two objects are equal

What is HashCode?

Convert the internal information (memory address, attribute value, etc.) of the object into a hash value through a specific rule, which is the HashCode of the object.

new A(2).hashCode()
  • The hashCode values of two different objects may be equal
  • Two objects with unequal hashcodes must not be the same object

When judging whether two objects are equal, the collection will first compare their hashcodes. If the hashcodes are not equal, it is considered that they are not the same object and can be added.

If the hashCode values are equal, it cannot be considered that the two objects are equal. Further judgment needs to be made through equals. If equals, the two objects are equal, otherwise the two objects are not equal

==: determines the value in the stack memory

For data of reference type, the address is stored in the stack memory, so at this time = = determines the reference address.

Basic data type. Specific values are stored in stack memory

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-ilmv1uui-163367401250) (C: \ users \ Deku \ appdata \ roaming \ typora \ typora user images \ image-20210815075023283. PNG)]

Variables are stored in the stack

Data data; The specific object (attribute) of the reference type is stored in the heap, and then the memory address of the object in the heap is assigned to the variable data in the stack. What is stored in data is the address

int num; The basic data type does not need heap memory. The variable is on the stack, and the value of the variable is directly stored on the stack.

6,TreeSet

LinkedHashSet and TreeSet are stored in an ordered and unique set of data, but the two orders here are different

The order of LinkedHashSet means that the storage order of elements is the same as the traversal order

The order of TreeSet means that all elements in the collection will be automatically sorted in ascending order. No matter what the storage order is, it must be output in ascending order during traversal (sorted according to ASCII code)

 /*
 * @see     Collection
 * @see     Set
 * @see     HashSet
 * @see     Comparable
 * @see     Comparator
 * @see     TreeMap
 * @since   1.2
 */

public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable
{
public class Collection01 {
    public static void main(String[] args) {
        TreeSet<Object> treeSet = new TreeSet<>();
//        treeSet.add("BCBC");
//        treeSet.add("CC");
//        treeSet.add("AC");
//        treeSet.add("AB");
//        treeSet.add("AA");
//        treeSet.add("BCBD");
        treeSet.add(new Data(1));
        treeSet.add(new Data(3));
        treeSet.add(new Data(2));
        treeSet.add(new Data(1));
        System.out.println(treeSet);
        Iterator iterator=treeSet.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}
class Data implements Comparable{
    private int num;

    public Data(int num) {
        this.num = num;
    }
/*
* A.compareTo(B)
*Return value
* 1: Indicates that A is greater than B
* 0: Indicates that A equals B
* -1: Indicates that A is less than B
* */
    @Override//compare ratio size
    public int compareTo(Object o) {
        if(o instanceof Data){
            Data data=(Data)o;
            if(this.num>data.num){
                return 1;
            }else if (this.num==data.num){
                return 0;
            }else{
                return -1;
            }
        }
        return 0;
    }

    @Override
    public String toString() {
        return "Data{" +
                "num=" + num +
                '}';
    }
}

7,Map

Key value: data dictionary,

The List and Set interfaces are all sub interfaces of the Collection. The Map interface is a completely independent system from the Collection.

List & Set VS Map

List & Set & collection can only operate on a single element. Map can operate on a pair of elements because the map operation space is a key value mapping.

 /*
 * @see HashMap
 * @see TreeMap
 * @see Hashtable
 * @see SortedMap
 * @see Collection
 * @see Set
 * @since 1.2
 */
public interface Map<K,V> {
    // Query Operations

The Map interface uses generics and defines two generics K and V. K represents Key, specifies the data type of Key element, and V represents the data type of Value element

  • int size();
    
  • boolean isEmpty();
    
  • boolean containsKey(Object key); //Determine whether the set contains a key
    
  • boolean containsValue(Object value);//Judge whether the collection contains Value
    
  • V get(Object key);//Get the Value corresponding to the key in the collection
    
  • V put(K key, V value);//Store a set of key values into the collection
    
  • V remove(Object key);//Delete the value corresponding to the key in the collection
    
  • void putAll(Map<? extends K, ? extends V> m);//Add another Map to the collection
    
  • void clear();//Clear all elements in the collection
    
  • Set<K> keySet();//Take out all Key values in the Set and return a Set
    
  • Collection<V> values();//Take out all value s in the Collection and return a Collection
    
  • Set<Map.Entry<K, V>> entrySet();//Output Map as Set
    
  • int hashCode();//Gets the hash value of the collection
    
  • boolean equals(Object o);//Compare two sets for equality
    

8. Common implementation classes of Map interface

  • HashMap: stores a group of unordered elements whose keys cannot be repeated and whose values can be repeated
  • Hashtable: stores a group of unordered elements whose keys cannot be repeated and whose values can be repeated
  • TreeMap: stores a group of elements that are ordered, whose keys cannot be repeated, and whose values can be repeated. They can be sorted by Key

The usage of Hashtable is basically the same as that of HashMap. The difference is that Hashtable is thread safe and has low performance. HashMap is non thread safe, but has high performance

  • The HashMap method is not decorated with synchronized, so it is non thread safe,
public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}
  • Hashtable, the method is decorated with synchronized, so it is thread safe
public synchronized V put(K key, V value) {
    // Make sure the value is not null
    if (value == null) {
        throw new NullPointerException();
    }

    // Makes sure the key is not already in the hashtable.
    Entry<?,?> tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    @SuppressWarnings("unchecked")
    Entry<K,V> entry = (Entry<K,V>)tab[index];
    for(; entry != null ; entry = entry.next) {
        if ((entry.hash == hash) && entry.key.equals(key)) {
            V old = entry.value;
            entry.value = value;
            return old;
        }
    }

    addEntry(hash, key, value, index);
    return null;
}

The data saved by HashMap and Hashtable are out of order. Another implementation class of Map, TreeMap, is mainly used to sort the elements in the collection according to the Key.

9. Collections tool class

Collection interface, parent interface of List and Set.

Collections is not an interface, but a tool class. It provides some operations on collections to facilitate developers to use and complete corresponding business functions.

Collections tool class for collections, Collection

Arrays tool class for arrays, Array

  • public static sort();//Sort collection
    
  • public static int binarySearch(List list,Object v);//Find the position of v in the combination. The set must be sorted in ascending order and binary search
    
  • private static get(List list, int index) //Returns the value of index in the collection
    
  • public static void reverse(List<?> list)//Output the set in reverse order
    
  • public static void swap(List<?> list, int i, int j)//Swaps two elements at a specified location in a collection
    
  • public static <T> void fill(List<? super T> list, T obj)//The data type of T is formed by combining the replacement of all elements in the
    
  • public static T min(Collection<? extends T> coll) //Returns the minimum value in the collection
    
  • public static T max(Collection<? extends T> coll, Comparator<? super T> //Returns the maximum value in the collection
    
  • public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal)//Replace old with new in the List
    
  • public static <T> boolean addAll(Collection<? super T> c, T... elements)//Add a meta to the collection
    

Variable parameters. When calling the method again, the parameters can be any number, but the types must match

public static void test(int... arg){
    
} 

However, the following expression can pass any type and any number of parameters, a specific form of polymorphism

public static void test(Object... arg){
    
}

The default output object format in Java: the full class name (fully qualified class name) to which the object belongs, the class name with package name + @ + the hash value of the object

JavaScript scripting language line by line compilation

Java must be compiled and executed uniformly. If there are ten lines of Java code, these 10 lines of code must be compiled and passed before being handed over to the JVM for execution

JS is executed line by line, and each line is counted as one line. If there are 10 lines of JS code, the execution starts line by line, and an error is reported until the fifth line, then lines 6-10 will not be executed, but the results of the first five lines that have been executed remain unchanged.

public class demo01 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        list.add("Hello");
        list.add("Word");
        Collections.addAll(list,"JavaEE","JavaME","Java");
        System.out.println(list);//[Hello, Word, JavaEE, JavaME, Java]
        Collections.sort(list);
        System.out.println(list);//[Hello, Java, JavaEE, JavaME, Word]
        //Binary search, binary search (the elements in the collection must be arranged in ascending order)
        int binarySearch = Collections.binarySearch(list, "Java");
        System.out.println("Java Subscript of"+binarySearch);//Subscript 1 of Java
        Collections.replaceAll(list,"Hello","Word");
        System.out.println(list);//[Word, Java, JavaEE, JavaME, Word]
    }
}

generic paradigm

Generics means that the data type of the information in the class is not specified during class definition, but is temporarily replaced by an identifier, and the specific data type is specified when the object is instantiated externally

//The type of a is specified when defining class A
public class A{
    private int a;
}
//When defining class A, the type of attribute is not specified
public class A<TE,M>{
    private T b;
    public E B(M m){
        return E;
    }
}
//When called
A<T,E,M> a=new A<>();

Advantages: this greatly improves the flexibility of the program and the extensibility of the class. Generics can refer to the data types of member variables in the class, the return value types of methods and the parameter types of methods.

1. Application of generics

Add generics to custom classes

public class Class name<Generic 1, generic 2, generic 3...>{
	private Generic 1 property name;
    public Generic 2 method name(Generic 3){
        Method body;
    }
}
public class Generics01 {
    public static void main(String[] args) {
        Time<Integer,String,Float> time=new Time<>();
        time.setHello(1);
        time.setWord("Hello");
        time.setJava(1.1f);
        System.out.println(time);//Time{Hello=1, Word = Hello, Java=1.1}
    }
}
class Time<T,E,M>{
    private T Hello;
    private E Word;
    private M Java;

    @Override
    public String toString() {
        return "Time{" +
                "Hello=" + Hello +
                ", Word=" + Word +
                ", Java=" + Java +
                '}';
    }

    public T getHello() {
        return Hello;
    }

    public void setHello(T hello) {
        Hello = hello;
    }

    public E getWord() {
        return Word;
    }

    public void setWord(E word) {
        Word = word;
    }

    public M getJava() {
        return Java;
    }

    public void setJava(M java) {
        Java = java;
    }
}

2. Generic wildcard

There is a method whose parameter is ArrayList. We hope that this method can accept both sets whose generic type is String and sets whose generic type is Intger. How to implement??

  • Polymorphism is not used in generics

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-0nnsdb9x-163367401250) (C: \ users \ Deku \ appdata \ roaming \ typora \ user images \ image-20210819144905021. PNG)]

public class generics02 {
    public static void main(String[] args) {
        ArrayList<String> arrayList=new ArrayList<>();
        ArrayList<Integer> arrayList1=new ArrayList<>();
        Test(arrayList);
        Test(arrayList1);
    }
    public static void Test(ArrayList<?> arrayList){}
}

ArrayList<?> Represents an object that can use any generic type, so test has generality.

3. Upper and lower bounds of generics

  • Upper limit: represents the specific data type during instantiation. It can be a subclass of the upper limit type or the upper limit type itself. It is represented by extensions
  • Lower bound: represents the specific data type during instantiation. It can be the parent of the lower bound type or the lower bound type itself. It is represented by super
Class name<Generic identity extends Upper class name>
Class name<Generic identity super Lower bound class name>
public class generics03<T> {
    public static void main(String[] args) {
        test(new generics03<Integer>());
        test(new generics03<Float>());
        test(new generics03<Number>());
        //---------------------------------
        test1(new generics03<String>());
        test1(new generics03<Object>());
    }
    /*
    * Generic upper bound
    * */
    public static void test(generics03<? extends Number> generics03){}
    /*
    * Generic lower bound
    * */
    public static void test1(generics03<? super String> generics03){}
}

4. Generic interface

Interface < >

public interface generics04<T> {
    public T getValue();
}

There are two ways to implement generic interfaces

  • Implementation classes continue to use generic IDS when defining
public class generics04Impl<T> implements generics04{
    private T obj;

    public generics04Impl(T obj) {
        this.obj = obj;
    }

    @Override
    public T getValue() {
        return this.obj;
    }
}
  • The implementation class directly gives the specific data type when defining
public class generics04Impl01 implements generics04<String> {
    private String Obj;
    public generics04Impl01(String obj){
        this.Obj=obj;
    }
    @Override
    public String getValue() {
        return this.Obj;
    }
}
public class generics04VO {
    public static void main(String[] args) {
        generics04Impl generics=new generics04Impl<String>("Hello");
        System.out.println(generics.getValue());
        generics04Impl01 generics2=new generics04Impl01("world");
        System.out.println(generics2.getValue());
    }
}

Java utility class

Similar to Arrays, Collections

1. Enumeration

Enum enum is a data type with definite value interval. It is essentially a class with the characteristics of simplicity, convenience and security

The value of enumeration is constrained to a specific range and can only be taken from this range

Why are there enumerations??????????

Because when describing the attributes of some objects, the value of the attribute cannot be defined arbitrarily, but must be taken in a specific interval

For the sake of data security, we can use enumeration to describe such data with specific value range

Enumeration refers to a type composed of a group of constants. It specifies a value range from which we can only take values

public enum  Week {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY;
}
final class Week extends Enum{
    public static final Week MONDAY;
    public static final Week TUESDAY;
    public static final Week WEDNSDAY;
    public static final Week THURSDAY;
    public static final Week FRIDAY;
    public static final Week SATURDAY;
    public static final Week SUNDAY;
    private static final Week $VALUES[];

    static{
        MONDAY = new Week("MONDAY",0);
        TUESDAY = new Week("TUESDAY",1);
        WEDNSDAY = new Week("WEDNSDAY",2);
        THURSDAY = new Week("THURSDAY",3);
        FRIDAY = new Week("FRIDAY",4);
        SATURDAY = new Week("SATURDAY",5);
        SUNDAY = new Week("SUNDAY",6);
        $VALUES[] = (new Week[]{
            MONDAY,TUESDAY,WEDNSDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY
        })
    }

    public static Week[] values(){
        return $VALUES.clone();
    }

    public static Week valueOf(String s){
        return Enum.valueOf(s);
    }

    private Week(String s,int i){
        super(s,i);
    }

}

2,Math

The Math class provides for developers

public class Test {
    public static void main(String[] args) {
        System.out.println("constant E: "+Math.E);//Constant E: 2.718281828459045
        System.out.println("constant PI: "+Math.PI);//Constant PI: 3.141592653589793
        System.out.println("9 Square root of:"+Math.sqrt(9));//Square root of 9: 3.0
        System.out.println("8 Cube root of:"+Math.cbrt(8));//Cube root of 8: 2.0
        System.out.println("2 Third power of:"+Math.pow(2,3));//Power 3 of 2: 8.0
        /*
        * Here, the 1 of int type is automatically converted to double type and becomes 1.0
        * Type conversion has only cast and automatic conversion
        * */
        System.out.println("Larger value:"+Math.max(6.5, 1));//Larger value: 6.5
        System.out.println("Absolute value:"+Math.abs(-1));//Absolute value: 1
        System.out.println(Math.ceil(10.0000001));//11.0
        System.out.println(Math.floor(10.999999));//10.0
        //0<Math.random()<1
        System.out.println("Random number:"+Math.random());//Random number: 0.71382027555706
        System.out.println("Random number:"+ (int) (Math.random() * 10));//Random number: 1
        System.out.println("rounding:"+Math.rint(5.5));//6.0
    }
}

3,Random

The class used to generate random numbers, and any interval can be specified to generate a random number within this interval

  • public Random();//Create a nonparametric random number constructor, using system time as the default seed
    
  • public Random(Long seed);//Create a random number constructor using a seed of type Long
    
  • public boolean nextBoolean();//Returns a random number of Boolean type
    
  • public double nextDouble();//Returns a random number of double type, between 0.0 and 1.0
    
  • public float nextFloat();//Returns a random number of float type, between 0.0 and 1.0
    
  • public int nextInt();//Returns an integer of type int
    
  • public int nextInt(n);//Returns a random number from 0 to N, [0,n)
    
    namedescribe
    public static sort()Sort collection
    public static int binarySearch(List list,Object v)To find the position of v in the list, the set must be ordered
    public static get(List list,int index)Returns the value of the index position in the list
    public static void reverse(List list)Output the list in reverse order
    public static void swap(List list,int i,int j)Swaps two elements at a specified location in a collection
    public static void fill(List list,Object obj)Replace all elements in the collection with obj
    public static Object min(List list)Returns the minimum value in the collection
    public static Object max(List list)Returns the maximum value in the collection
    public static boolean replaceAll(List list,Object old,Object new)Replace old with new in the list set
    public static boolean addAll(List list,Object... obj)Add elements to the collection

4,String

java uses the String class to create and manipulate strings

  • String instantiation

1. Direct assignment

String str="HelloWord";

2. Create objects through constructors

String str=new String("HelloWord");
public class Test{
    public static void main(String[] arg){
        String str="Hello";
        String Str2=new String("Hello");
        System.out.println(str==str2);//false
        System.out.println(str.equals(str2)));//ture
        
    }
}

String is not a basic data type

5. Common methods of String

methoddescribe
public String()Create an empty string object
public String(String value)Create a string object with value
public String(char value[])Converts a char array to a string object
public String(char value[],int offset, int count)Converts a char array of a specified range to a string object
public String(byte value[])Converts a byte array to a string object
public String(byte value[],int offset, int count)Converts a byte array of a specified range into a string object
public int length()Gets the length of the string
public boolean isEmpty()Determine whether the string is empty
public char charAt(int index)Returns the character of the specified subscript
public byte[] getBytes()Returns the byte array corresponding to the string
public boolean equals(Object anObject)Judge whether two string values are equal
public boolean equalsIgnoreCase(Object anObject)Judge whether two string values are equal (case ignored)
public int compareTo(String value)Sort strings
public int compareToIgnoreCase(String value)Sort regardless of case
public boolean startsWith(String value)Determines whether the string starts with value
public boolean endsWith(String value)Determines whether the string ends with value
public int hashCode()Returns the hash value of a string
public int indexOf(String str)Returns the subscript of str in a string
public int indexOf(String str,int formIndex)Finds the subscript of a string from the specified location
public String subString(int beginIndex)Intercepts the string from the specified location
public String subString(int beginIndex,int endIndex)Intercepts the string of the specified interval
public String concat(String str)Append string
public String replaceAll(String o,String n)Replace all o's in the string with n's
public String[] split(String regex)Splits the target with the specified string and returns an array
public String toLowerCase()Turn lowercase
public String toUpperCase()Capitalize
public char[] toCharArray()Convert string to character array

6,StringBuffer

Once a String object is created, its value cannot be modified (the original value cannot be modified. Once it is modified, it will be a new object. As long as it is changed, a new object will be created)

After modification, the memory space will be reopened to store the new object.

Why can't the value of String be modified? Will a new object be created after modification? Instead of modifying the original object?

  • Because the underlying String uses an array to store values, the length of the array cannot be modified once it is created, resulting in the above problems

StringBuffer can solve the problem of wasting space resources caused by frequent String modification.

The underlying layer of StringBuffer also uses arrays to store values

  • The default length of the StringBuffer array is 16, and the parameterless structure is used to create objects
public StringBuffer() {
        super(16);
    }
  • Create an object using a parameterized construct. Array length = length of value + 16
public StringBuffer(int capacity) {
        super(capacity);
    }
public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
    }
public StringBuffer(CharSequence seq) {
        this(seq.length() + 16);
        append(seq);
    }

Append, append and splice

public class Random01 {
    public static void main(String[] args) {
        StringBuffer stringBuffer=new StringBuffer();
        StringBuffer stringBuffer1=new StringBuffer("String");
        /*stringBuffer Bottom array length 16
        * stringBuffer1 Underlying array length 21
        * */
        stringBuffer.append("String");
        System.out.println(stringBuffer1.equals(stringBuffer));//false
        System.out.println(stringBuffer1.toString().equals(stringBuffer.toString()));//true
          System.out.println(stringBuffer.length());//6
        System.out.println(stringBuffer1.length());//6
    }
}
  • The. length() method returns not the length of the underlying array, but its effective length (the length of the value)

reflection??? Once the StringBuffer is created, there will be 16 bytes of space to modify by default. However, how to deal with it once the length of the appended string exceeds 16??

StringBuffer will not reopen a new space, but will expand the capacity on the original basis. It will expand the capacity of the underlying array by calling the parent class ensureCapacityInternal() method, leaving the reference unchanged

stringBuffer.ensureCapacity(1);

StringBuffer is a common method. StringBuffer is thread safe but inefficient. StringBuilder is thread unsafe but efficient.

HashMap: unsafe thread and high efficiency

Hashtable: thread safe and inefficient

methoddescribe
public StringBuffer()Create an empty StringBuffer object
public StringBuffer(String str)Create a StringBuffer object with the value str
public synchronized int length()Returns the length of the StringBuffer
public synchronized char charAt(int index)Returns the character at the specified position
public synchronized StringBuffer append(String str)Additional content
public synchronized StringBuffer delete(int start,int end)Deletes the value of the specified interval
public synchronized StringBuffer deleteCharAt(int index)Deletes the character at the specified position
public synchronized StringBuffer replace(int start,int end,String str)Replace the value of the specified interval with str
public synchronized String substring(int start)Intercepts the string from the specified position to the end
public synchronized String substring(int start,int end)The intercepted string starts from start and ends at end
public synchronized StringBuffer insert(int offset,String str)Insert str at the specified location
public int indexOf(String str)Finds the position of the specified character from scratch
public int indexOf(String str,int fromIndex)Finds the position of the specified character starting from fromIndex
public synchronized StringBuffer reverse()Reverse
public synchronized String toString()Convert to String

Reading data does not need to consider thread safety, because there is no security risk in this operation.

Date class

  • java.util.Date

Date indicates the current system time

public class Data01 {
    public static void main(String[] args) {
        Date date = new Date();//Wed Aug 25 15:32:56 CST 2021
        /*
        * h It's 12 hour hh:mm:ss
        * H It is 24-hour HH:mm:ss
        * */
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String str = simpleDateFormat.format(date);//2021-08-25 03:35:34
    }
}
  • java.util.Calendar

Calendar is used to complete the logical operation of date data

Operation idea:

1. Transfer date data to Calendar (Calendar provides many static constants, which are specially used to record date data)

constantdescribe
public static final int YEARyear
public static final int MONTHmonth
public static final int DAY_OF_MONTHDays in months
public static final int DAY_OF_YEARDays in years
public static final int HOUR_OF_DAYhour
public static final int MINUTEminute
public static final int SECONDsecond
public static final int MILLSECONDmillisecond

2. Call relevant methods for operation

methoddescribe
public static Calendar getInstance()Get Calendar instantiation object
public void set(int field,int value)Assign values to static constants
public int get(int field)Gets the value of a static constant
public final Date getTime()Convert Calendar to Date object
public class Calendar01 {
    public static void main(String[] args) {
        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd");
        //Calculate the week today is the week of 2021
        Calendar calendar=Calendar.getInstance();
        System.out.println(format.format(calendar.getTime()));//2021-08-25 current time
        calendar.set(Calendar.YEAR,2021);
        calendar.set(Calendar.MONTH,7);//January is zero and August is seven
        calendar.set(Calendar.DAY_OF_MONTH,24);
        int week = calendar.get(Calendar.WEEK_OF_YEAR);
        System.out.println(week);//35
        //What month is the 63 days after today
        int day=calendar.get(Calendar.DAY_OF_YEAR);
        System.out.println(day);//Today is the first day of several years 236
        day+=63;
        calendar.set(Calendar.DAY_OF_YEAR,day);
        Date date=calendar.getTime();
        System.out.println(format.format(date));//2021-10-26
        //What month is the 63 days before today
        calendar.set(Calendar.DAY_OF_YEAR,calendar.get(Calendar.DAY_OF_YEAR)-63);
        date=calendar.getTime();
        System.out.println(format.format(date));//2021-08-24
    }
}

IO stream

1. File class

  • java.io.File use the constructor of this class to create a constructor to represent a specific file in the hard disk as a java object
methoddescribe
public File(String pathname)Create objects from paths
public String getName()Get file name
public String getParent()Get the directory where the file is located
public File getParentFile()Get the File object corresponding to the directory where the File is located
public String getPath()Get file path
public boolean exists()Determine whether the file exists
public boolean isDirectory()Determine whether the object is a directory
public boolean isFile()Judge whether the object is a file
public long length()Gets the size of the file
public boolean createNewFile()Creates a new file based on the current object
public boolean delete()delete object
public boolean mkdir()Create a directory based on the current object
public boolean renameTo(File file)Rename an existing object
  • According to the direction, it can be divided into input flow and output flow
  • According to the unit, it can be divided into byte stream and character stream
  • According to the function, it can be divided into node flow and processing flow

2. Byte stream

According to the direction, it can be divided into input byte stream and output byte stream

InputSteam,OutputSteam

1 byte = 8-bit binary number 01010101

Common methods of InputStream

methoddescribe
int read()Read data in bytes
int read(byte b[])Store data into an array of byte type and return the length of valid data in the array
int read(byte b[],int off,int len)Store the data into the specified interval of byte array and return the length of the array
byte[] readAllBytes()Store all data into byte array and return
int available()Returns the number of unread data in the current data stream
void close()Close data flow

OutputStream

methoddescribe
void write(int b)Output data in bytes
void write(byte b[])Output data from byte array
void write(byte b[],int off,int len)Outputs the data of the specified interval in the byte array
void close()Close data flow
void flush()Synchronize the data in the buffer stream to the output stream
//What month is the 63 days before today
    calendar.set(Calendar.DAY_OF_YEAR,calendar.get(Calendar.DAY_OF_YEAR)-63);
    date=calendar.getTime();
    System.out.println(format.format(date));//2021-08-24
}

}



# IO stream

##  1. File class

- [ ] java.io.File Using the constructor of this class, you can create a constructor to convert a specific file in the hard disk to java Object

| method                               | describe                           |
| ---------------------------------- | ------------------------------ |
| public File(String pathname)       | Create objects from paths               |
| public String getName()            | Get file name                     |
| public String getParent()          | Get the directory where the file is located             |
| public File getParentFile()        | Get the corresponding directory of the file File object |
| public String getPath()            | Get file path                   |
| public boolean exists()            | Determine whether the file exists               |
| public boolean isDirectory()       | Determine whether the object is a directory             |
| public boolean isFile()            | Judge whether the object is a file             |
| public long length()               | Gets the size of the file                 |
| public boolean createNewFile()     | Creates a new file based on the current object         |
| public boolean delete()            | delete object                       |
| public boolean mkdir()             | Create a directory based on the current object           |
| public boolean renameTo(File file) | Rename an existing object           |

- According to the direction, it can be divided into input flow and output flow
- According to the unit, it can be divided into byte stream and character stream
- According to the function, it can be divided into node flow and processing flow

## 2. Byte stream

According to the direction, it can be divided into input byte stream and output byte stream

InputSteam,OutputSteam

1 byte = 8 Bit binary number 01010101

InputStream common method

| method                               | describe                                                   |
| ---------------------------------- | ------------------------------------------------------ |
| int read()                         | Read data in bytes                                   |
| int read(byte b[])                 | Store data in byte Returns the length of valid data in the array |
| int read(byte b[],int off,int len) | Store data in byte Returns the length of the array within the specified interval of the array         |
| byte[] readAllBytes()              | Store all data in byte Array and return                         |
| int available()                    | Returns the number of unread data in the current data stream                         |
| void close()                       | Close data flow                                             |

OutputStream

| method                                 | describe                           |
| ------------------------------------ | ------------------------------ |
| void write(int b)                    | Output data in bytes           |
| void write(byte b[])                 | take byte Data output in array         |
| void write(byte b[],int off,int len) | take byte Data output of the specified interval in the array |
| void close()                         | Close data flow                     |
| void flush()                         | Synchronize the data in the buffer stream to the output stream |

Tags: Python Java Database

Posted on Thu, 07 Oct 2021 11:02:42 -0400 by phpnewby1918