线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒。J
<span style="font-size:18px;">new Thread(){
public void run() {
while(true){
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();</span>
ava 虚拟机允许应用程序并发地运行多个执行线程。
创建新执行线程有两种方法。一种方法是将类声明为 Thread
的子类。该子类应重写Thread
类的run
方法。如下所示:
Runnable
接口的类。该类然后实现 run
方法。然后可以分配该类的实例,在创建 Thread
时作为一个参数来传递并启动。如下所示:
<span style="font-size:18px;"> //直接new runnable接口,实现run方法
new Thread(new Runnable(){
public void run() {
while(true){
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"second thread").start();</span>
创建线程的操作已经完成,在这里我就要考考大家了,下面代码中哪个线程先执行
<span style="font-size:18px;"> new Thread(new Runnable(){
public void run() {
while(true){
try {
Thread.sleep(1000);
System.out.println("1--------------"+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"second thread"){
public void run() {
while(true){
try {
Thread.sleep(1000);
System.out.println("2--------------"+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();</span>
看到这里的朋友应该有争论了,每个人都有自己的想法。我先来给大家分析一下,1线程是实现Runnable接口,然后有的run方法,2线程是继承thread类,也就继承的是1线程的类,那么2线程重写的也就是2线程的run方法,所以毫无疑问,是线程2重写了线程1,也就是说线程2把线程1给覆盖了,所以只有线程2会执行。
下面我写一个多个线程访问一个方法,产生高并发脏读脏写的简单例子
<span style="font-size:18px;"> final Print print=new Print();
//循环两个线程个一百次
for(int i=0;i<100;i++){
new Thread(new Runnable(){
public void run() {
while(true){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
print.print("tianwanggaidihu");
}
}
},"second thread").start();
new Thread(){
public void run() {
while(true){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
print.print("baotazhenheyao");
}
}
}.start();
}
}
//内部类
static class Print{
public synchronized void print(String name){
// synchronized 互斥锁,多个线程进来的时候保证是同一把锁
for(int i=0;i<name.length();i++){
//把传进的字符串循环打印
System.out.print(name.charAt(i));
}
System.out.println();
}
}</span>
如果我不加互斥锁 synchronized 那么打印出来的字符串会毫无章法,乱七八糟,加上互斥锁的作用就是一个线程访问完另一个才能访问。
多线程有很多很经典的面试题,我给大家整理了两套,先来一个简单的
<span style="font-size:18px;"> new Thread(new Runnable(){
public void run() {
for (int i = 1; i <=30; i++) {
try {
Thread.sleep(100);//跑一米需要0.1秒,所以一米让线程休息0.1秒
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if( i % 10 ==0){
System.out.println("兔子跑了"+i+"米");
try {
Thread.sleep(1000*10);//跑十米休息十秒
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
},"rabbit").start();
new Thread(new Runnable(){
public void run() {
for (int i = 1; i <=30; i++) {
try {
Thread.sleep(1000);//跑一米需要一秒,所以一米让线程休息一秒
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if( i % 10==0){
System.out.println("乌龟跑了"+i+"米");
try {
Thread.sleep(1000);//跑十米休息一秒
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
},"turtle").start();</span>
这道题的答案是代表兔子的线程先执行完毕。
子线程循环 10 次,接着主线程循环 5 次,接着又回到子线程循环 10 次,接着再回到主线程循环5次,如此循环5次。参考代码如下:
<span style="font-size:18px;"> final Service service = new Service();
//为节省资源,把main当做主线程,为主线程设值
Thread.currentThread().setName("主线程");
//子线程
new Thread(new Runnable() {
public void run() {
for (int i = 1; i <= 5; i++) {
try {
service.sub();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}, "子线程").start();
for (int i = 1; i <= 5; i++) {
service.main();
}
}
static class Service {
//设置一个变量,当前线程是主线程时isMain为true
boolean isMain = true;
public synchronized void main() throws Exception {
//当前进来是主线程时让它等待,是子线程时绕过循环继续执行
while(!isMain){
this.wait();
}
//循环五次
for (int i = 1; i <= 5; i++) {
System.out.println("main" + i);
}
//主线程执行完,把他变为false
isMain=false;
//叫醒子线程
this.notify();
}
public synchronized void sub() throws Exception {
//当前进来是主线程时让它等待,是子线程时绕过循环继续执行
if(isMain){
this.wait();
}
//循环十次
for (int i = 1; i <= 10; i++) {
System.out.println("sub" + i);
}
//子线程执行完,把他变为true
isMain=true;
//叫醒主线程
this.notify();
}
}</span>
这就是本人对多线程的理解,本次的分享希望能给大家带来帮助。