一.新建一个线程
方式1:继承Thread
//新建线程继承Thread
public class newthread extends Thread{
//重写父类中的run方法
@Override
public void run() {//run中写自己的业务逻辑
System.out.println("测试线程1");
//让该线程休眠一秒
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
//调用
public class testThread {
public static void main(String[] args) {
//测试newthread;
newthread newthread = new newthread();
newthread.start();
//newthread.run();错误:start首先启动线程最终会执行线程中的run()方法,如果只是调用run不用start就是简单调用一个方法,并不是真正启动一个线程,而是把run执行完毕才向下执行
}
}
注意事项:一个进程的主线程结束,但是还有其他线程在运行时,并不会结束这个程序,会执行完剩下的程序
方式二:实现Runnable接口
原因:java是单继承的在某些情况下,一个类可能已经继承了某个父类,这时再用继承Thread类来城建线程无法实现
代码实现:
//新建线程类实现Runnable接口
public class Run implements Runnable{
int count=0;
@Override
public void run() {
while(true){
System.out.println("第二种方法创建线程"+(++count)+Thread.currentThread().getName());
//休眠1s
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if(count==10){
break;
}
}
}
//调用方法
public class runTest {
public static void main(String[] args) {
Thread thread = new Thread(new Run());
thread.start();
}
}
注意:上述两种方法是没有本质区别的都是调用Runnable中的start方法中的start0; 注意:上述两种方法是没有本质区别的都是调用Runnable中的start方法中的start0;
二.Runnable的方法实现多线程
代码实现:
public class Thread3 {
public static void main(String[] args) {
test1 test1 = new test1();
test2 test2 = new test2();
Thread thread = new Thread(test1);
Thread thread1 = new Thread(test2);
thread.start();
thread1.start();
}
}
class test1 implements Runnable{
int count1=0;
@Override
public void run() {
while (true) {
//每隔一秒输出hello
System.out.println("hello"+(count1++));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if(count1==10){
break;
}
}
}
}
class test2 implements Runnable{
@Override
public void run() {
int count2 = 0;
while (true) {
//每隔一秒输出hello
System.out.println("world"+(count2++));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if(count2==10){
break;
}
}
}
}
三.线程的常用方法
1.setName,设置线程名称
2.getName返回该线程的名称
3.start使该线程开始执行,java虚拟机底层调用该线程的start0方法
4.run调用线程对象的run方法
5.setPriority更该线程的优先级
6.getPriority获取线程的优先级
7.sleep在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
8.interrupt 中断线程
9.yield线程的礼让,让出cpu让其他线程执行,但礼让时间不确定,所以不一定礼让成功
10.join线程插队,插队的线程一旦插队成功一定会优先执行完插入的程序的所有任务
四.用户线程与守护线程
1.用户线程:也叫工作线程
2.守护线程:一般是为了工作线程服务的,当所有的用户线程结束守护线程自动结束
3.常见的守护线程:垃圾回收机制
守护线程举例:
public class sh {
public static void main(String[] args) throws InterruptedException {
shxc shxc = new shxc();
shxc.setDaemon(true);//将子线程设置为守护线程,注意先设置后start,此时主线程结束后子线程会自动结束
shxc.start();
for (int i = 0; i < 10; i++) {
System.out.println("主线程在工作");
Thread.sleep(1000);
}
}
}
class shxc extends Thread{
public void run(){
for (; ;){//死循环
try {
Thread.sleep(50);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("守护线程");
}
}
}
五.解决线程安全问题
卖票案例:
1.自动锁:synchronized,自动上锁和释放锁,同一时刻只让一个线程执行2.手动锁ReentrantLock,需要手动上锁解锁
2.手动锁ReentrantLock,需要手动上锁解锁
//自动锁
public class suo {
public static void main(String[] args) {
sell sell = new sell();
Thread thread = new Thread(sell);
Thread thread1 = new Thread(sell);
thread.start();
thread1.start();
}
}
class sell implements Runnable{
private int ticket=100;
@Override
public void run() {
while(true){
synchronized (this){
if (ticket>0){
ticket--;
System.out.println(Thread.currentThread().getName()+"剩余票数"+ticket);
}else {
break;
}
}
}
}
}
//手动锁
public class Soudongsuo {
public static void main(String[] args) {
sds sds = new sds();
Thread thread = new Thread(sds);
Thread thread1 = new Thread(sds);
thread1.start();
thread.start();
}
}
class sds implements Runnable{
private int ticket=100;
private Lock l=new ReentrantLock();//手动创建一个锁
@Override
public void run() {
while(true){
l.lock();
if(ticket>0){
ticket--;
System.out.println(Thread.currentThread().getName()+"剩余票数"+ticket);
}else{
break;
}
l.unlock();
}
}
}