java multithreading concurrency and thread pool

1. Inherit the Thread class to create a thread class

public class FirstThreadTest extends Thread {
    public void run(){
        System.out.println("这里是线程的执行方法");
    }

    public static void main(String[] args) {
        //获得线程
        FirstThreadTest thread = new FirstThreadTest();
        System.out.println("线程名称为:"+thread.getName());
        //启动线程
        thread.start();
        System.out.println("main方法也是一个线程:"+Thread.currentThread().getName());
    }
}

Results of the:

线程名称为:Thread-0
main方法也是一个线程:main
这里是线程的执行方法

2. Create a thread class through the Runnable interface
(1) Define the implementation class of the runnable interface, and rewrite the run() method of the interface. The method body of the run() method is also the thread execution body of the thread;
(2) Create Runnable implements an instance of the class, and uses this instance as the target of Thread to create a Thread object, which is the real thread object;
(3) Call the start() method of the thread object to start the thread.

public class RunnableThreadTest implements Runnable {

    public void run() {
        System.out.println("这里是线程方法");
        System.out.println("线程名为:" + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        System.out.println("main方法线程:" + Thread.currentThread().getName());
        RunnableThreadTest rtt = new RunnableThreadTest();
        new Thread(rtt, "新线程1").start();
        new Thread(rtt, "新线程2").start();
    }

}

Results of the

main方法线程:main
这里是线程方法
线程名为:新线程1
这里是线程方法
线程名为:新线程2

The specific difference between the two thread creation: http://www.cnblogs.com/whgw/archive/2011/10/03/2198506.html (expansibility and resource sharing)

Multi-threaded concurrency

The problem of multi-threaded concurrency mainly involves two aspects: multi-threaded shared data synchronization problem and data inconsistency caused by concurrency;

1. Multi-threaded shared data synchronization problem The
following code:

/**
 * 两个工人一起搬砖
 */
public class Banzhuan {
    public static void main(String[] args) {
        // 一个工厂
        Factory factory = new Factory();
         /**
           * p1线程和p2线程都是由factory这个实例创建的
           * 那么p1调用外部类的getZhuanTou()方法就相当于调用的是factory这个实例的getZhuanTou(),同样的,p2调用的也是factory这个实例的getZhuanTou().
           * 那么这里就出现了两个线程同时访问factory的getZhuanTou()方法。
           * 而factory的getZhuanTou()方法又对zhuanTou这个属性进行了zhuanTou--操作。
           * 换句话说,两个线程同时访问了factory的数据zhuanTou.这时候就可能产生线程安全问题。
           */
        // 同一个工厂的两个工人
        Person p1 = factory.getPerson();
        Person p2 = factory.getPerson();
        p1.start();
        p2.start();
    }
}

// 工厂
class Factory {
    int zhuanTou = 20;// 一共20块砖头

    public int getZhuanTou() {
        if (zhuanTou == 0) {
            throw new RuntimeException(Thread.currentThread().getName()+ ",没有砖头搬了!");
        }
        Thread.yield();
        return zhuanTou--;

    }

    // 工人
    class Person extends Thread {
        // 不停的搬砖
        public void run() {
            while (true) {
                // 获取线程名(工人名) 及 剩下砖头数
                System.out.println(getName() + "搬了第" + getZhuanTou() + "块砖头");
                // 当线程的run方法中出现了异常,且我们没有 解决,那么该线程终止并死亡。但不会影响 当前进程中的其他线程。
                Thread.yield();
            }
        }
    }

    // 获取工人
    public Person getPerson() {
        return new Person();
    }
}

Results of multiple runs:
write picture description here

This does not always make mistakes. If you run it several times, you may encounter various errors , such as moving the same brick, such as moving one less brick, such as moving to 0 and then continuing to move... The
reason is that : For example, there are still 15 bricks left, and worker p1 is getting the 15th brick when he moves it, but has not registered to reduce one brick (that is, zhuanTou– has not been run), at this time worker p2 also picks up the brick and then registers it When I see that there are 15 bricks left, there are actually only 14 bricks left...
Solution:
synchronized: When it is used to modify a method or a code block, it can ensure that at most one thread executes the segment at the same time code.
So change the getZhuanTou() method to the following:

public int getZhuanTou() {
        synchronized (this) {
            if (zhuanTou == 0) {
                throw new RuntimeException(Thread.currentThread().getName()+",没有砖头搬了!");
            }
            Thread.yield();
            return zhuanTou--;
        }
    }

Why not lock this keyword in the method? Try to lock in the smallest scope, so it will run more efficiently.

2. Data inconsistency due to concurrency
Reference : https://my.oschina.net/clopopo/blog/149368

ThreadLocal : Provides a copy of the variable for each thread, so that each thread does not access the same object at a certain time.

First of all, ThreadLocal is not used to solve the problem of multi-threaded access to shared objects. In general, the object passed to the thread through ThreadLocal.set() is the object used by the thread itself. arrived. Different objects are accessed in each thread;

In addition, it is said that ThreadLocal enables each thread to maintain an independent object, not through ThreadLocal.set(), but through the operation of the new object in each thread to create an object, each thread creates one, Not a copy or a duplicate of something.

Again, note that when each thread saves an object (non-basic type data) it should be a new object rather than a reference to an object, as follows:

private static ThreadLocal<Index> local = new ThreadLocal<Index>() {
        @Override
        protected Index initialValue() {
            return new Index(); //注意这里
        }
    };

Case code:

public class ThreadLocalTest {

        //创建一个Integer型的线程本地变量
    public static final ThreadLocal<Integer> local = new ThreadLocal<Integer>() {
        @Override
        protected Integer initialValue() {
            return 0;
        }
    };
    public static void main(String[] args) throws InterruptedException {
        Thread[] threads = new Thread[5];
        for (int j = 0; j < 5; j++) {       
               threads[j] = new Thread(new Runnable() {
                @Override
                public void run() {
                                        //获取当前线程的本地变量,然后累加5次
                    int num = local.get();
                    for (int i = 0; i < 5; i++) {
                        num++;
                    }
                                        //重新设置累加后的本地变量
                    local.set(num);
                    System.out.println(Thread.currentThread().getName() + " : "+ local.get());

                }
            }, "Thread-" + j);
        }

        for (Thread thread : threads) {
            thread.start();
        }
    }
}

Running results:
Thread-0 : 5
Thread-4 : 5
Thread-2 : 5
Thread-1 : 5
Thread-3 : 5

--------------------------------------------------------------------------------------------------

3. Summary:
ThreadLocal and Synchonized are both used to solve multi-threaded concurrent access. However, there are essential differences between ThreadLocal and synchronized:
1. The synchronized keyword mainly solves the problem of multi-threaded shared data synchronization, and the use of ThreadLocal mainly solves the problem of data inconsistency in multi-threading due to concurrency;
2. Synchronized uses the lock mechanism to make variables or A block of code should only be accessed by one thread at a time. ThreadLocal provides a copy of the variable for each thread, so that each thread does not access the same object at a certain time, thus isolating the data sharing of data by multiple threads. Synchronized is just the opposite, it is used to obtain data sharing when communicating between multiple threads;
synchronized and ThreadLocal comparison: http://blog.csdn.net/huyongl1989/article/details/8088841

Thread Pool

When there are many requests to be processed, if only one person handles it, it is conceivable that it will make the people in the queue wait for a long time, so a thread pool is needed, and when a request comes, it will be taken out from the thread pool. A thread handles it, and when the processing is completed, it is taken back into the thread pool. However, it is not easy to implement a powerful thread pool by yourself. After java1.5, a class library for thread pools is specially provided.

Java provides four thread pools through the Executors interface, which are:
newCachedThreadPool creates a cacheable thread pool. If the length of the thread pool exceeds the processing needs, it can flexibly recycle idle threads. If there is no recovery, create a new thread;
newFixedThreadPool creates a fixed-length thread Pool, which can control the maximum number of concurrent threads, and the excess threads will wait in the queue;
newScheduledThreadPool creates a fixed-length thread pool to support timing and periodic task execution;
newSingleThreadExecutor creates a single-threaded thread pool, which only uses unique Worker threads execute tasks to ensure that all tasks are executed in the specified order (FIFO, LIFO, priority);
here is a brief look at the thread pool newFixedThreadPool:

public class ThreadPoolExecutorTest {
    public static void main(String[] args) {
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            final int index = i;
            fixedThreadPool.submit(new Runnable() {
                public void run() {
                    try {
                        System.out.println(Thread.currentThread().getName()+"---->"+index);
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}

运行:
pool-1-thread-1—->0
pool-1-thread-3—->2
pool-1-thread-2—->1
pool-1-thread-3—->3
pool-1-thread-2—->5
pool-1-thread-1—->4
pool-1-thread-3—->6
pool-1-thread-1—->8
pool-1-thread-2—->7
pool-1-thread-3—->9

Because the thread pool size is 3, each task sleeps for 2 seconds after outputting the index, so 3 numbers are printed every two seconds.
fixedThreadPool.submit(Runnable task) or execute method will call the thread's run method;

 

Thread pool reference address: http://blog.csdn.net/u012385190/article/details/52486393

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326443627&siteId=291194637