1.多线程概念
进程:一个正在运行的程序就可以看作是一个进程。每个进程都有自己独立
的内存空间。
线程:一个程序的执行顺序控制流就可以看作是一个线程。
进程和线程的区别:
1.每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较
大的开销。
2.线程可以看成时轻量级的进程,同一类线程共享代码和数据空间,每个
线程有独立的运行栈和程序计数器(PC),线程切换的开销小。
多进程:在操作系统中能同时运行多个程序(任务)
多线程:在同一应用程序中有多个顺序流同时执行,在一个进程里可以有1条
或多条线程,但是至少要有一条线程。多线程能够提高程序的执行效率。
线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。
2.main线程(主线程)
在程序里有一个public static void main(String[] args)方法,这个方法是程序
的入口,这是一个固定的写法。
当程序启动时,JVM虚拟机会自动的创建main线程(主线程),在主线程里
会自动的调用main()方法,就会执行main()方法里的代码。我们编写的代码都
是写在main()方法中,所以我们写的代码都是在主线程(main线程)执行的。
3.创建子线程的(两种方式)
Thread类:描述线程里的属性(线程的名称,线程的优先级,线程执行的任
务),基于面向对象的思想就把线程的属性封装成Thread类。
Thread类的方法:
a.普通方法
getName():获取线程对象的名称。
start():启动线程。
b.静态方法:类名.方法名
currentThread():获取当前正在执行的线程对象。
Thread curThead = Thread.currentThread();
System.out.println(curThead.getName());
4.Thread类常用方法
静态方法:类名.方法名()
currentThread():返回一个正在执行的线程对象。
sleep():让当前线程睡醒指定毫秒数。
普通方法:
getName():获取线程对象的名称
start():开启子线程
(1)sleep():让当前线程睡醒指定毫秒数,不会释放锁。是Thread类的静态方法,可以在任意位置使用。
//睡眠1秒
Thread.sleep(1000);
(2)isAlive():判断线程是否还“活”着,即线程是否还未终止。
线程的优先级:
线程的优先级越高表示这个线程执行的概率越高。
线程优先级值的范围:1~10,最低1,最高10.
(3)getPriority():获取线程的优先级。
(4)setPriority():设置线程的优先级。
(5)join():调用某线程的该方法,将当前线程与该线程“合并”,即等待该线程结束,再恢复当前线程的运行。
(6)yield():让出CPU,当前线程进入就绪队列等待调度。
(7)wait():让线程进入等待池wait pool进入阻塞状态并释放锁,直到notify()或者notifyAll()唤醒。是object类的对象方法,只能在互斥锁(同步锁)里使用。
(8)notify()或者notifyAll()唤醒等待池wait pool里的线程。
5.互斥锁(同步锁)(重点)
解决多线程安全问题就是用同步锁。
a.给代码加锁
public void run()
{
Thread.sleep(500);
//在run()方法里的访问变量加锁
//类名.class是钥匙
synchronized(类名.class)
{//开始加锁
xinXi1.num++;
System.out.println(Thread.currentThread().getName() + xinXi1.num);
}//释放锁
}
例子:
public class xinXi1
{
public static int num = 11;
public static void main(String[] args)
{
System.out.println("num="+xinXi1.num);
addThread addThread = new addThread("线程1");
subThread subThread = new subThread("线程2");
addThread.start();
subThread.start();
}
}
//加法子线程继承Thread
class addThread extends Thread{
public addThread(String name){
super(name);}@Overridepublic void run(){ try { addThread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
//给代码加锁
synchronized (xinXi1.class)
{
xinXi1.num++;
System.out.println(addThread.currentThread().getName()+"加法后="+xinXi1.num);
}
}
}
//减法子线程继承Thread
class subThread extends Thread{
public subThread(String name){
super(name);}@Overridepublic void run(){ try { subThread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (xinXi1.class) { xinXi1.num--; System.out.println(subThread.currentThread().getName()+"减法后="+xinXi1.num); } }
}
b.给方法加锁
例子:
public class xinXi1
{
public static int num = 11;
public static void main(String[] args)
{
System.out.println("num="+xinXi1.num);
addThread addThread = new addThread("线程1");
subThread subThread = new subThread("线程2");
addThread.start();
subThread.start();
}
//给方法加锁
public static synchronized void add(){
xinXi1.num++;
System.out.println(addThread.currentThread().getName()+"加法后="+xinXi1.num);
}
//给方法加锁
public static synchronized void sub(){
xinXi1.num--;
System.out.println(subThread.currentThread().getName()+"减法后="+xinXi1.num);
}
}
class addThread extends Thread{
public addThread(String name){super(name);
}
@Override
br/>super(name);
}
@Override<br <="" a="">public void run()
{
try
{
subThread.sleep(3000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
//线程里调用方法
xinXi1.sub();
}
}
注意事项:
1.synchronized(){}大括号里的代码就是加锁的代码,注意加锁会影响程序
的性能,除非涉及到多线程数据安全才需要加锁,其他情况建议不要加锁。
加锁的代码要尽量的少。
super(name);
}
@Override<br/" rel="nofollow">