一、线程
1.1 多线程
自定义线程类:
public class MyThread extends Thread{
public MyThread(String name){
super(name);
}
public void run(){
for (int i = 0; i < 20; i++) {
System.out.println(getName()+i);
}
}
}
测试
public class Demo1 {
public static void main(String[] args) {
System.out.println("main线程");
MyThread mt = new MyThread("新线程");
mt.start();//开启了一个新的线程
for (int i = 0; i < 20; i++) {
System.out.println("main:"+i);
}
}
}
1.2 thread
(1)构造方法
public Thread() :分配一个新的线程对象。
public Thread(String name) :分配一个指定名字的新的线程对象。
public Thread(Runnable target) :分配一个带有指定目标新的线程对象。
public Thread(Runnable target,String name) :分配一个带有指定目标新的线程对象并指定名字。
(2)常用方法
public void start() :线程开始执行, Java虚拟机会调用此线程的run方法。
public void run() :此线程要执行的任务在此处定义代码。
public static void sleep(long millis) :停止执行millis秒。
public String getName() :获取当前线程名称。
public static Thread currentThread() :返回对当前正在执行的线程对象的引用。
setDaemon(), 设置一个线程为守护线程, 该线程不会单独执行, 当其他非守护线程都执行结束后,
自动退出。
join(int), 当前线程暂停, 等待指定的线程执行结束后, 当前线程再继续 可以等待指定的毫秒.
1.3 Runable
定义Runnable接口的实现类,并重写该接口的run()方法. 创建Runnable实现类的实例,将此实例带入Thread的构造方法中,,然后调用线程对象的start()方法来启动线程。
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
测试
public class Demo {
public static void main(String[] args) {
MyRunnable mr = new MyRunnable();
//创建线程对象
Thread t = new Thread(mr, "小强");
t.start();
for (int i = 0; i < 20; i++) {
System.out.println("旺财 " + i);
}
}
}
1.4 Thread和Runnable的区别
实现了Runable接口能实现资源共享。避免了单继承的局限,. 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。
二、线程安全
线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写 操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步, 否则的话就可能影响线程安全。 Java中提供了同步机制 (synchronized)来解决这种问题。
2.1 synchronized
synchronized 关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。
(1)同步代码块
synchronized(同步锁){
同步操作的代码
}
同步锁:对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁.
- 锁对象 可以是任意类型。
- 多个线程对象 要使用同一把锁。
注意:在任何时候,最多允许一个线程拥有同步锁,谁拿到锁就进入代码块,其他的线程只能在外等着。
(2)同步方法
public synchronized void method(){
可能会产生线程安全问题的代码
}
对于非static方法,同步锁就是this。
对于static方法,我们使用当前方法所在类的字节码对象(类名.class)。
2.2 Lock锁
public void lock() :加同步锁。
public void unlock() :释放同步锁
2.3 Lock锁和sychronized的区别
synchronized既可以加在方法上,也可以加载特定代码块上,而lock需要显示地指定起始位置和终止
位置。
synchronized是托管给JVM执行的,lock的锁定是通过代码实现的,它有比synchronized更精确的线
程语义。
性能上的不同:lock接口的实现类ReentrantLock,不仅具有和synchronlzed相同的并发性和内存语义,还多了超时的获取锁、定时锁、等候和中断锁等。在竞争不是很激烈的情况下,synchronized的性能
优于ReentrantLock,竞争激烈的情况下synchronized的性能会下降的非常快,而ReentrantLock则基本不变。
锁机制不同:synchronized获取锁和释放锁的方式都是在块结构中,当获取多个锁时,必须以相反的顺序释放,并且是自动解锁。而Lock则需要开发人员手动释放,井且必须在finally中释放,否则会引起死锁。