为了使用户体验更好,服务的相应速度更快。现如今硬件不断发展,软件要求也逐渐提高,都是为了一个字:快。
①并行就是两个任务同时运行,就是甲任务进行的同时,乙任务也在进行(需要多核CPU)
②并发是指两个任务都请求运行,而处理器只能接收一个任务,就是把这两个任务安排轮流进行,由于时间间隔较短,使人感觉两个任务都在运行(秒杀系统)
wait是Object类中的方法,表示释放该线程执行权,需用Object中的notify|notifyAll唤醒。而sleep只是“阻塞”当前线程指定时间,不释放执行权,是Thread类中的方法。
(1). 原始构成a. synchronized是关键字属于JVM层面monitor对象,每个java对象都自带了一个monitor,需要拿到monitor对象才能做事情monitorenter(底层是通过monitor对象来完成,其实wait/notify等方法也依赖monitor对象,只能在同步块或方法中才能调用wait/notify等方法),进入monitorexit:退出b. lock是api层面的锁,主要使用ReentrantLock实现
(2). 使用方法a. synchronized不需要用户手动释放锁,当synchronized代码完成后系统会自动让线程释放
对锁的占用b. ReentrantLock则需要用户手动释放锁若没有主动释放锁,就有可能会导致死锁的现象
(3). 等待是否可中断?a. synchronized不可中断,除非抛出异常或者正常运行完成b. ReentrantLock可中断(设置超时时间tryLock(long timeout,TimeUnit unit),调用interrupt方法中断)
(4). 加锁是否公平a. synchronized非公平锁b. ReentrantLock两者都可以,默认是非公平锁,构造方法可以传入boolean值,true为公平锁,false为非公平锁
(5). 锁绑定多个Conditiona.synchronized没有b.ReentrantLock用来实现分组唤醒需要唤醒线程们,可以精确唤醒,而不是像synchronized要么随机唤醒一个\要么多个
public class ThreadDemo {public static void main(String[] args) {MyThread myThread = new MyThread();myThread.start();for (int i = 0; i < 100; i++) {System.out.println("我是线程"+Thread.currentThread().getName()+"输出功能:"+i);}}
}class MyThread extends Thread {@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println("我是线程"+Thread.currentThread().getName()+"输出功能:"+i);}}
}
public class RunnableDemo {public static void main(String[] args) {MyThreadRunnable myThreadRunnable = new MyThreadRunnable();Thread t = new Thread(myThreadRunnable);t.start();for (int i = 0; i < 100; i++) {System.out.println("我是线程"+Thread.currentThread().getName()+"输出功能:"+i);}}}class MyThreadRunnable implements Runnable {@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println("我是线程"+Thread.currentThread().getName()+"输出功能:"+i);}}
}
(1).查看源码a.继承Thread:由于子类重写了Thread类的run(),当调用start()时,直接找子类的run()方法b.实现Runnable:构造函数中传入了Runnable的引用,成员变量记住了它,start()调用run()方法时内部判断成员变量Runnable的引用是否为空,不为空编译时看的是Runnable的run(),运行时执行的是子类的run()方法(2).继承Threada.好处是:可以直接使用Thread类中的方法,代码简单b.弊端是:如果已经有了父类,就不能用这种方法(3).实现Runnable接口a.好处是:即使自己定义的线程类有了父类也没有关系,因为有了父类可以实现接口,而且接口
可以多现实的b.弊端是:不能直接使用Thread中的方法需要先获取到线程对象后,才能得到Thread的方法,
代码复杂
public class ThreadCallDemo {public static void main(String[] args) {CallThread callThread = new CallThread();FutureTask futureTask = new FutureTask(callThread);new Thread(futureTask).start();try {Object sum = futureTask.get();System.out.println(sum);} catch (Exception e) {e.printStackTrace();}}
}class CallThread implements Callable{@Overridepublic Object call() throws Exception {int sum = 0;for (int i = 0; i < 100; i++) {System.out.println(i);sum += i;}return sum;}
}
此文不做记录,见后续学习笔记。
//FileWriterMyThread my1 = new MyThread();MyThread my2 = new MyThread();//void setName(String name):将此线程的名称更改为等于参数 namemy1.setName("线程1");my2.setName("线程2");my1.start();my2.start();
线程有两种调度模型:
ThreadPriority tp1 = new ThreadPriority();ThreadPriority tp2 = new ThreadPriority();ThreadPriority tp3 = new ThreadPriority();tp1.setName("线程1");tp2.setName("线程2");tp3.setName("线程3");//设置正确的优先级tp1.setPriority(5);tp2.setPriority(10);tp3.setPriority(1);tp1.start();tp2.start();tp3.start();
说明: