在谈线程之前,我们至少应该了解下进程是什么,简单来说,进程就是正在运行的应用程序,每一个正在运行的应用程序就会对应一个进程。
那么线程,就是依赖于进程而存在的,一个进程可以开启多个线程,由一个对象所开启的所有线程使用的是同一份成员属性。
多线程的两种方案:
继承Thread类
实现Runable接口
1.继承Thread类
public class MyThread extends Thread{
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println(i);
}
}
}
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThread mt = new MyThread();
//代码在主线程执行,不会开辟新线程
mt.run();
//创建一个子线程,并开启这个子线程执行他的run方法
mt.start();
}
}
2.实现Runable接口
public class MyThread implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
System.out.println(i);
}
}
}
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThread mt = new MyThread();
//这里的MyThread类仅仅是实现了Runnalble接口的一个类,但是start方法在Thread类中
//我们需要使用public Thread(Runnable target)这个构造方法
Thread thr = new Thread(mt);
thr.start();
}
}
线程的调度和控制
线程休眠(Thread.sleep(毫秒值))
线程名称(setName(),getName();)
线程的调度及优先级setPriority(10)(注意默认值是5,区间在1-10之间)
线程优先级:就是设置你抢占到cpu执行权的概率
public class MyThread extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<50;i++){
try {
Thread.sleep(100);//在此异常我们只能抓取,不能抛出,因为父类中没有抛出异常
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.getName()+" "+i);
}
}
}
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
MyThread mt3 = new MyThread();
mt1.setName("A君");
mt2.setName("B君");
mt3.setName("C君");
mt2.setPriority(10); //只是优先执行的概率,并不是绝对优先
mt1.start();
mt2.start();
mt3.start();
}
}
多线程安全问题
一般情况下判断一个对象是否是线程安全的,看以下三点:
A:是否是多线程环境
B:是否有共享数据
C:是否有多条语句操作共享数据