创建线程的第一种方式:继承Thread ,由子类复写run方法。步骤:
- 1,定义类继承Thread类;
- 2,目的是复写run方法,将要让线程运行的代码都存储到run方法中;
- 3,通过创建Thread类的子类对象,创建线程对象;
- 4,调用线程的start方法,开启线程,并执行run方法。 线程状态:
创建线程的第二种方式:实现一个接口Runnable。 步骤:
- 1,定义类实现Runnable接口。
- 2,覆盖接口中的run方法(用于封装线程要运行的代码)。
- 3,通过Thread类创建线程对象;
- 4,将实现了Runnable接口的子类对象作为实际参数传递给Thread类中的构造函数。 为什么要传递呢?因为要让线程对象明确要运行的run方法所属的对象。
- 5,调用Thread对象的start方法。开启线程,并运行Runnable接口子类中的run方法。
线程的状态
- **新建:start()
- **运行:具备执行资格,同时具备执行权;
- **冻结:sleep(time),wait()—notify()唤醒;线程释放了执行权,同时释放执行资格;
- **临时阻塞状态:线程具备cpu的执行资格,没有cpu的执行权;
- **消亡:stop()
这篇博客是看完黑马视频教程总结的,如有错误,请多指教
简单代码块
两种方法,线程使用 例如:
public class ThreadTest {
public static void main(String[] args) {
//第一种Thread使用方法
ThreadOne one1 = new ThreadOne();
one1.start();
//设计线程名称
ThreadOne one2 = new ThreadOne("第一种线程名称");
one2.start();
//第二种Runnable使用方法
ThreadTwo two=new ThreadTwo();
Thread two1=new Thread(two);
two1.start();
}
}
/**
* 第一种方法 继承thread类
*
*/
class ThreadOne extends Thread {
public ThreadOne(){}
//为线程设置名字
public ThreadOne (String name){
super.setName(name);//为线程设置名字
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "线程启动");
super.run();
}
}
/**
* 第二种方法,实现Runnable接口
*/
class ThreadTwo implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "线程启动");
}
}
- **为什么将Runnable接口的子类对象传递给Thread的构造函数?
因为,自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程去指定对象的run方法,就必须明确run方法所属的对象 - **实现方式和继承方式有什么区别呢?
实现方式好处:避免单继承的局限性。
在定义线程时,建立使用实现方式。 - **两种方式区别:
继承Thread:线程代码存放Thread子类方法中。
实现Runnable,线程代码存在接口的子类的run方法中。
线程同步
为什么要使用线程同步
* java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), *
* 多条语句在操作同一个县城共享数据是,一个线程对多条语句值执行了一部分,还没有执行完另一个线程参与进来执行,导致共享数据的错误 *
- * java对于多献臣过的安全问题提供专业的解决方法,就是同步代码块 *
- ** synchronized(对象){
需要同步的代码块
}
同步的前提:
- * 必须要有两个或者两个以上的线程 *
- * 必须是多个线程使用同一个锁(同一个对象) *
这样做
- ** 好处:结局了多线程的安全问题
- ** 弊端:多线程需要判断锁,较为消耗资源
注意:如果在run()方法上加锁,那么只有第一个线程会执行,直到执行完后其他的线程才会执行,造成后几个线程分不到任务
简单代码块
线程同步 例如:
/**
* 线程同步
*/
public class ThreadTest {
public static void main(String[] args) {
//线程同步的问题
ThreadTwo thread = new ThreadTwo();
Thread thread1 = new Thread(thread);
Thread thread2 = new Thread(thread);
Thread thread3 = new Thread(thread);
Thread thread4 = new Thread(thread);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
/**
* 实现Runnable接口
*/
class ThreadTwo implements Runnable {
private static int count = 100;
@Override
// 如果在run()方法上加锁,那么只有第一个线程会执行,直到执行完后其他的线程才会执行,造成后几个线程分不到任务
// public synchronized void run() {
public void run() {
while (true) {
synchronized (this) {
// 如果是实现Runnable接口,而且只创建一个对象可以用自身的对象区锁住
if (count == 0) {
System.out.println("到0了!");
break;
}
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(count-- + "=========" + Thread.currentThread().getName() + " id:"
+ Thread.currentThread().getId());
}
}
}
}
如果同步函数是静态
- ** 静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象。XXX.class该对象的类型是Class
简单代码块
两种方法,线程使用 例如:
/**
* 线程同步
*/
public class ThreadTest {
public static void main(String[] args) {
// 线程同步的问题
ThreadTwo thread = new ThreadTwo();
Thread thread1 = new Thread(thread);
Thread thread2 = new Thread(thread);
Thread thread3 = new Thread(thread);
Thread thread4 = new Thread(thread);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
/**
* 实现Runnable接口
*/
class ThreadTwo implements Runnable {
private static int count = 100;
private static boolean flag=true;
@Override
public void run() {
while (flag) {
synchronized (ThreadTwo.class) {
method();
}
}
}
//当方法为静态是要用xxx.class锁定
public static void method() {
if(count>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(
count-- + "=========" + Thread.currentThread().getName() + " id:" + Thread.currentThread().getId());
}else{
System.out.println(Thread.currentThread().getName() + "到0了!");
flag=false;
}
}
}
在单例设计模式中有一个饿汉式采用类的字节码对象同步
/**
* 饿汉式
* @author chris
*
*/
class Single {
private static final Single single =new Single();
private Single(){}
public Single getInstance(){
return single;
}
}
/**
*懒汉式
* @author chris
*
*/
class Single2{
private static Single2 single=null;
private Single2(){}
public static Single2 getInstance(){
if(single!=null){//两次判断提高性能,避免每次都判断锁
synchronized(Single2.class){
//用该类的字节码对象同步 解决多线程下出问题
if(single!=null){
single=new Single2();
}
}
}
return single;
}
}