1.进程与线程
①进程是系统进行资源分配和调度的一个独立单位,线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源,但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
②一个任务或应用程序就是一个进程,进程与进程之间不能数据共享,同属一个进程的各个线程之间可以数据共享。
③main方法是一个主线程(或main线程)。
2.多线程的创建与启动方式
①继承自Thread类,并重写run()方法,调用Thread类的 start()方法启动线程;
public class ThreadDemo01 extends Thread //继承自Thread类
ThreadDemo01 thread01 = new ThreadDemo01();
thread01.start();
②实现java.lang.Runnable接口,并实现run()方法,这种方式定义的子线程需要借助Thread 类的 start()方法来启动。
public class ThreadDemo02 implements Runnable //实现Runnable接口
ThreadDemo02 thread02 = new ThreadDemo02();
Thread th = new Thread(thread02);
th.start();
3.创建多线程的两种方式有什么区别
当线程类继承自Thread类后就不能继承其他类,而实现Runnable接口还可以实现其他接口并且实现其他的类。
4.线程的分类
①守护线程:由普通线程到主仆线程,必须在start()方法之前使用setDaemon(true)标记为守护线程;
ThreadDemo01 thread01 = new ThreadDemo01();
thread01.setDaemon(true);//标记为守护线程,在start()方法之前设置
thread01.start();
②join线程:在start()方法之后调用join()方法,join线程执行完后再执行main线程。
ThreadDemo01 thread01 = new ThreadDemo01();
thread01.start();
thread01.join();
5.产生线程安全问题的条件
在单线程中不会出现线程安全问题,当多个线程同时对同一个对象的实例变量(属性)操作时会引起线程同步问题。
举个例子:
假如两个线程分别用thread-1和thread-2表示,某一时刻,thread-1和thread-2都读取到了数据X,那么可能会发生这种情况:
thread-1去检查数据库中是否存在数据X,然后thread-2也接着去检查数据库中是否存在数据X。结果两个线程检查的结果都是数据库中不存在数据X,那么两个线程都分别将数据X插入数据库表当中。这个就是线程安全问题,即多个线程同时访问一个资源时,会导致程序运行结果并不是想看到的结果。这里面,这个资源被称为:临界资源(也有称为共享资源)。也就是说,当多个线程同时访问临界资源(一个对象,对象中的属性,一个文件,一个数据库等)时,就可能会产生线程安全问题。
6.如何解决线程安全问题
①互斥锁:在Java中,可以使用synchronized关键字来标记一个方法或者代码块,当某个线程调用该对象的synchronized方法或者访问synchronized代码块时,这个线程便获得了该对象的锁,其他线程暂时无法访问这个方法,只有等待这个方法执行完毕或者代码块执行完毕,这个线程才会释放该对象的锁,其他线程才能执行这个方法或者代码块。
synchronized(this) {
//出现线程安全问题的代码块
}
②使用ReentrantLock类
ReentrantLock reentrantLock = new ReentrantLock();//创建对象
reentrantLock.lock();
//出现线程安全问题的代码
reentrantLock.unlock();//一般写在finally语句中
7.如何创建线程安全集合
List<String> list = Collections.synchronizedList(new ArrayList<String>())
Set<String> set = Collections.synchronizedSet(new HashSet<String>())
Map<String,String> map = Collections.synchronizedMap(new HashMap<String,String>())
网友评论