Java多线程例子

Sukuna发布

Java多线程的思路就是一个:如果保证线程之间能够协作

首先我们得了解什么叫作线程,我们电脑里面有很多程序在运行,比如说QQ,微信等等,一个程序就是一个进程,进程是电脑分配内存空间的最小单位,但是进程里面有很多线程,比如说QQ,QQ里面有接受消息的,有显示动画的,有发送消息的,有很多很多线程,线程就是CPU执行命令的最小单位,一个CPU在一个时间内只能执行一个线程的任务

线程可以生成,运行,杀死,让其休眠.我们可以巧妙使用线程来完成许多协作的问题

我们可以构建线程池:如果有大量的任务要运行,会导致频繁创建新线程、销毁线程。线程池维护多个创建好的线程,同时可以让多个任务“复用”线程,避免了线程的重复创建和销毁。

我们还可以给资源上锁

可以使用synchronized(this) { …}给()里面的资源上锁,通过加锁:一个线程要进入同步方法,首先拿到锁,进入方法后立刻上锁,导致其他要进入这个方法的线程被阻塞(等待锁):表达式expr求值结果必须是一个对象的引用,因此可以通过对任何对象加锁来同步语句块,如果expr指向的对象没有被加锁,则第一个执行到同步块的线程对该对象加锁,线程执行该语句块,然后解锁;如果expr指向的对象已经加了锁,则执行到同步块的其它线程将被阻塞.expr指向的对象解锁后,所有等待该对象锁的线程都被唤醒,注意只是执行到同步块的线程加锁,而且如果同步块不是静态上下文的话就只对这个对象加锁

2. 给定下列程序:
public class Holder {
	private int data = 0;
	public int getData () {return data;}
	public synchronized void inc (int amount) {
		int newValue = data + amount;
		try {Thread.sleep(5);
		} catch (InterruptedException e) {}
		data = newValue;
	}
	public void dec (int amount) {
		int newValue = data - amount;
		try {Thread.sleep(1);
		} catch (InterruptedException e) {}
		data = newValue;
	}
}
public static void main (String [] args) {
	ExecutorService es = Executors.newCachedThreadPool();
	Holder holder = new Holder ();
	int incAmount = 10, decAmount = 5, loops = 100;
	Runnable incTask = () -> holder.inc(incAmount);
	Runnable decTask = () -> holder.dec(decAmount);
	for (int i = 0; i < loops; i++) {
		es. execute(incTask);
		es. execute(decTask);
	}
	es. shutdown ();
	while (! es. isTerminated ()) {}
}
下列说法正确的是_____A______。
A. 当一个线程进入holder对象的inc方法后,holder对象被锁住,因此其他线程不能进入inc方法和dec方法
B. 当一个线程进入holder对象的inc方法后,holder对象被锁住,因此其他线程不能进入inc方法,但可以进入dec方法
C. 当一个线程进入holder对象的dec方法后,holder对象被锁住,因此其他线程不能进入dec方法和inc方法
D. 当一个线程进入holder对象的dec方法后,holder对象被锁住,因此其他线程不能进入dec方法,但可以进入inc方法

当然可以使用lock.lock()和unlock()方法给this加锁

还可以使用Condition类来加锁,注意一定要声明锁才能使用Condition里面的await和signalALL方法,这个可以进行线程协作和信号通信

还有多线程的请求是并发的不是串行的,对于并发的请求,可以构建一个List来进行处理

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ReusableThread extends Thread{
//private Runnable runTask = null; //保存接受的线程任务
//使用一个列表接收所有需要完成的任务
private LinkedList<Runnable> tasks = new LinkedList<>();
private static Lock lock = new ReentrantLock();
private static Condition waitTask = lock.newCondition();

//只定义不带参数的构造函数
public ReusableThread(){
    super();
}

/**
* 覆盖Thread类的run方法
*/
@Override
public void run() {
    while (true) {
        lock.lock();
        try{
            if (tasks.size() == 0) {
                try {
                    waitTask.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //移除并获取列表第一个任务,运行
            tasks.removeFirst().run();
        }finally {
            lock.unlock();
        }
    }
}

/**
* 提交新的任务
* @param task 要提交的任务
*/
public void submit(Runnable task){
    lock.lock();
    try{
        tasks.add(task);
        waitTask.signalAll();
    }finally {
        lock.unlock();
    }
}

public static void main(String[] args){
    Runnable task1 = new Runnable() {
        @Override
        public void run() {
            System.out.println("Thread " + Thread.currentThread().getId() + ": is running " + toString());
            try { Thread.sleep(200); }
            catch (InterruptedException e) { e.printStackTrace(); }
        }
        @Override
        public String toString() {
            return "task1";
        }
    };
    Runnable task2 = new Runnable() {
        @Override
        public void run() {
            System.out.println("Thread " + Thread.currentThread().getId() + " is running " + toString());
            try { Thread.sleep(100); }
            catch (InterruptedException e) { e.printStackTrace(); }
        }
        @Override
        public String toString() {
            return "task2";
        }
    }
}
分类: 杂记

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用*标注

隐藏

总访问量:1162102    今日访问量:266    您是今天第:266 位访问者