**进程:**进程是内存中运行的应用程序,每个进程拥有独立的内存空间。
**线程:**是进程中的一个执行路径,线程可以并发,一个进程至少有一个线程
线程是在进程基础上的进一步划分,一个进程可有多条线程,
(1)继承Thread类
public class ThreadTest{
public static void main(String[] args){
MyThread t1 = new MyThread(); //创建线程对象
t1.start(); //线程启动
}
static class MyThread extends Thread{
//继承Thread类
public void run(){
//任务
System.out.println("Thead1线程执行了")
}
}
}
(2)实现Runnable接口
public class RunnableTest{
public static void main(String[] args){
Runnable r = new MyRunnable();
Thread t1 = new Thread(r);
t1.start();
}
static class MyRunnable implements Runnable{
public void run(){
System.out.println("Thread线程执行了!");
}
}
}
1、构造器
(1)、Thread()
无参构造方法
(2)、Thread(Runnable target)
传一个Runnable接口的实现子类
(3)、Thread(Runnable target,String name)
传一个Runnable接口的实现子类并设置线程名
2、常用方法
(1)、start()
void
启动线程。
(2)、currentThread
static Thread
返回当前正在执行的线程对象的引用 一般使用Thead.currentThread.getName()
来获取线程名称。
(3)、getId()
long
返回当前进程的表示,作用于getName()相同。
(4)、getName()
String
返回该线程的名称。
(5)、getPriority
int
返回该线程的优先级。
(6)、setPriority(int newPriority)
void
设置线程的优先级。
MAX_PRIORITY
: 线程可以拥有的最大优先级。 10
MIN_PRIORITY
:线程可以拥有的最低优先级。 1
NORM_PRIORITY
:分配给线程的默认优先级。 5
(7)、interrupt()
void
中断此线程,相当于打一个中断标记。
(8)、setDaemon(boolean on)
void
设置当前线程为守护线程
(9)、setName(String name)
void
设置该线程的名字。
(10)、sleep(long millis)
static void
使当前线程休眠
(11)、toString
String
将当前线程作为字符串输出。
线程安全:所谓线程安全就是所需线程不能并发,需要排队执行。
1、隐式锁:隐式锁分为同步代码块和同步方法两种实现方式,都是运用synchronized关键字,并并且都是创建锁后自动开关锁。
//模拟购票实现:synchronized代码块
public class Demo1{
public static void main(String[] args){
Ticket t1 = new Ticket();
t1.start();
}
static class Ticket extends Thread{
private int count = 10; //初始票数为10张票
public void run(){
while(true){
synchronized(this){
//synchronized代码块
if(count>0){
System.out.println("正在出票中····");
count--;
System.out.println("余票为:"+i);
}
}
}
}
}
}
需要注意的一点:
在使用synchronize(){}代码块时,括号中的内容必须是实现同一个任务的共享的对象。
//模拟购票实现:synchronized 同步方法
public class Demo2 {
public static void main(String[] args) {
Object o = new Object();
// 同步方法
Runnable run = new Ticket();
new Thread(run).start(); //启动第一个线程
new Thread(run).start(); //启动第二个线程
new Thread(run).start(); //启动第三个线程
}
static class Ticket implements Runnable{
//总票数
private int count = 10; //初始票数为10张
@Override
public void run() {
while (true) {
boolean flag = sale();
if(!flag){
break;
}
}
}
public synchronized boolean sale(){
//需要排队执行的代码
if (count > 0) {
//卖票
System.out.println("正在准备卖票");
try {
Thread.sleep(1000); //休眠1秒,方便看的更细致
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName()+"卖票结束,余票:" + count);
return true;
}
return false;
}
}
}
2、显式锁 Lock:隐式锁更倾向于面向对象,是先创建锁对象,然后调用方法,开关锁。
public class Demo3{
public static void main(String[] args){
Ticket t1 = new Ticket();
t1.start();
}
static class Ticket extends Thread{
private Lock lock = new ReentrantLock();
private int count = 10;
public void run(){
while(true){
lock.lock(); //上锁
if(count>0){
System.out.println("正在出票中····");
count--;
System.out.println("余票为:"+i);
}
lock.unlock(); //解锁
}
}
}
}
1、定义及优缺点:
非公平锁:公平锁是指多个线程按照申请锁的顺序来获得锁,线程直接进入队列中排队,队列中的第一个线程才能获得锁。
优点:等待锁的线程不会饿死。
缺点:效率较低。
非公平锁:非公平锁是多个线程加锁时直接尝试获得锁,获取不到才会进入等待队列的队尾等待。
优点:效率高,线程有几率不阻塞获得锁。
缺点:在队列中的线程有几率会饿死,或者要等待很久才能获得锁。
2、Java中的公平锁与非公平锁
(1)隐式锁全部为非公平锁,因为是抢占式调度。
(2)在显示锁中,在创建Lock对象时,(Lock lock = new ReentrantLock()),括号中可以传一个布尔类型值,传入true则为公平锁,否
则为非公平锁,默认情况为false。
1、死锁产生的条件:
(1)互斥。共享资源同时只能被一个线程访问。
(2)占有且等待。线程T1在取得共享资源A的时候,请求等待资源B的时候并不释放资源A。
(3)不可抢占。其他线程不能强行抢占线程的资源。
(4)循环等待条件。线程T1在持有资源A1,同时在请求等待获取资源B,线程T2在持有资源B,然后在请求等待线程T1的持有资源,
形成了交叉闭环申请。
Java通过Executors提供四种线程池,分别为:
newCashedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool :创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool: 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor: 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,
LIFO, 优先级)执行。
//缓存线程池:
public class CashedThreadPoolTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程启动了!!!");
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程启动了!!!");
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+
"线程启动了!!!");
}
});
}
}
/*执行结果:
pool-1-thread-1线程启动了!!!
pool-1-thread-2线程启动了!!!
pool-1-thread-2线程启动了!!!
*/
//不定长线程池
public class FixedThreadPoolTest {
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(2);
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程启动了!!!");
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程启动了!!!");
}
});service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程启动了!!!");
}
});
}
}
/*执行结果:
pool-1-thread-1线程启动了!!!
pool-1-thread-2线程启动了!!!
pool-1-thread-1线程启动了!!!
*/
//单线程线程池
public class SingleThreadPoolTest {
public static void main(String[] args) {
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程启动了!!!");
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程启动了!!!");
}
});
}
}
/*执行结果:
pool-1-thread-1线程启动了!!!
pool-1-thread-1线程启动了!!!
*/
//周期性定长线程池
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolTest {
public static void main(String[] args) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
/*执行一次
* 第一个参数:定时执行的任务
* 第二个参数:第一次执行任务的延迟时间
* 第三个参数:时间单位
scheduledExecutorService.schedule(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程启动了!!!");
}
},2, TimeUnit.SECONDS);*/
/**
* 第一个参数:定时执行的任务
* 第二个参数:第一次执行任务的延迟时间
* 第三个参数:周期性时间(每隔多长时间执行一次)
* 第四个参数:时间单位
*/
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程启动了!!!");
}
},5,2,TimeUnit.SECONDS);
}
}
public class LambdaTest {
public static void main(String[] args) {
Thread t1 = new Thread(() -> System.out.println("线程执行了"),"t1");
t1.start();
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
}
}