线程Thread
【一个进程里面包含多个线程,线程就是程序运行的最小单位】
CPU的工作方式:多核多线程
一.创建线程的方式
1.方式一:
创建一个新的执行线程有两种方法。 一个是将一个类声明为Thread的子类。 这个子类应该重写Thread里面的run方法。
例如:
public class LolThread extends Thread{
@Override
public void run() {
//覆写一百次runn方法
for (int i = 0; i < 100; i++) {
System.out.println("aaaaaaaaaaaaa");
}
}
}
public class ThreadTest {
//其中有三个线程 main lolThread.start()
public static void main(String[] args) {
LolThread lolThread = new LolThread();
MusicThread musicThread = new MusicThread();
//开启一个独立线程,等待被cpu选中,选中以后自己回去调用对象里面的run方法
lolThread.start(); //只是开启一个线程,不会立刻去运行里面的任务逻辑
musicThread.start();
System.out.println("------------------------------------");
System.out.println("------------------------------------");
System.out.println("------------------------------------");
System.out.println("------------------------------------");
}
}
2.方式二:
创建一个类 实现Runnabl接口 覆写run方法
创建一个实现类对象作为参数的传入Thread对象里面,并调用start方法
例如:
public class BoThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("正在播放电影");
}
}
}
public class ThreadTest {
public static void main(String[] args) {
KuaiBoThread kuaiBoThread = new KuaiBoThread();
Thread thread = new Thread(kuaiBoThread);
thread.start();
System.out.println("------------------------------------");
System.out.println("------------------------------------");
System.out.println("------------------------------------");
System.out.println("------------------------------------");
}
}
3.相关面试题:
3.1这两种创建线程的方式哪种好
答:一般来说是实现 Java中是单继承多实现
3.2启动线程的时候:调用run和start有什么区别?
答:调用run不是去开启线程去运行,仅仅只是简单的对象调用方法
买票案例:
继承---------------------------------------
public class TicketThread extends Thread{
private static int num = 50;
TicketThread(){}
TicketThread(String name){
super(name);
}
@Override
public void run() {
while (num>0){
sale();
}
}
public synchronized void sale(){
if (num>0) {
System.out.println(super.getName()+"购买票为:"+num);
num--;
}
}
}
public class TicketTest {
public static void main(String[] args) {
TicketThread t1 = new TicketThread("12306");
TicketThread t2 = new TicketThread("携程");
TicketThread t3 = new TicketThread("飞猪");
t1.start();
t2.start();
t3.start();
}
}
实现--------------------------------
public class TicketThread implements Runnable{
private static int num = 50;
@Override
public void run() {
while (num>0){
sale();
}
}
public synchronized void sale(){
if (num>0) {
System.out.println(Thread.currentThread().getName()+"购买票为:"+num);
num--;
}
}
}
public class TicketTest {
public static void main(String[] args) {
TicketThread t = new TicketThread();
new Thread(t,"12306").start();
new Thread(t,"携程").start();
new Thread(t,"飞猪").start();
}
}
二.线程安全:
在代码执行的过程中,有一些不正常的情况,所以会实行线程切换
解决线程安全:
1.同步代码块:
synchronized(同步对象){
会发生线程问题的代码
}
同步对象:
可以写同步的资源
例如:
继承
public class TicketThread extends Thread{
private static int num = 50;
TicketThread(){}
TicketThread(String name){
super(name);
}
@Override
public void run() {
while (num>0){
sale();
}
}
public synchronized void sale(){
if (num>0) {
System.out.println(super.getName()+"购买票为:"+num);
num--;
}
}
}
测试
public class TicketTest {
public static void main(String[] args) {
TicketThread t1 = new TicketThread("12306");
TicketThread t2 = new TicketThread("携程");
TicketThread t3 = new TicketThread("飞猪");
t1.start();
t2.start();
t3.start();
}
}
2.同步方法:
在方法的修饰符后面添加synchronized
步方法解决线程安全问题
例如:
继承
public class TicketThread extends Thread{
private static int num = 50;
TicketThread(){}
TicketThread(String name){
super(name);
}
@Override
public void run() {
while (num>0){
sale();
}
}
public synchronized void sale(){
if (num>0) {
System.out.println(super.getName()+"购买票为:"+num);
num--;
}
}
}
测试
public class TicketTest {
public static void main(String[] args) {
TicketThread t1 = new TicketThread("12306");
TicketThread t2 = new TicketThread("携程");
TicketThread t3 = new TicketThread("飞猪");
t1.start();
t2.start();
t3.start();
}
}
3.Lock锁
Lock上锁
unLock 释放锁
例如:
实现
public class TicketThread extends Thread{
private static int num = 5000;
private static ReentrantLock reentrantLock = new ReentrantLock();
TicketThread(){}
TicketThread(String name){
super(name);
}
@Override
public void run() {
//新建一把锁
while (num>0){
reentrantLock.lock();//上锁
if (num>0) {
System.out.println(super.getName()+"购买票为:"+num);
num--;
}
reentrantLock.unlock();//释放锁
}
}
}
测试
public class TicketTest {
public static void main(String[] args) {
TicketThread t1 = new TicketThread("12306");
TicketThread t2 = new TicketThread("携程");
TicketThread t3 = new TicketThread("飞猪");
t1.start();
t2.start();
t3.start();
}
}