一个单CPU的机器,如何同时执行多个线程?请简述其原理。
单核CPU在任何时间点上,只能运行一个进程;宏观并行、微观串行。
操作系统(OS)会为每个线程分配执行时间,多个线程,彼此间完成不同的工作,交替执行。
(线程的创建)有以下代码
public class Example implements Runnable{
@Override
public void run() {
while(true) {
}
}
public static void main(String[] args) {
Example ex1 = new Example();
Example ex2 = new Example();
Example ex3 = new Example();
ex1.run();
ex2.run();
ex3.run();
}
}
选择正确答案:
A,代码编译失败,因为ex2.run()无法获得执行
B.代码编译成功,存在3个可运行的线程
C.代码编译成功,存在1个可运行的线程
C
public class Example implements Runnable{
public static void main(String[] args) {
Thread t = new Thread(new Example());
t.start();
}
public void run(int limit) {
for(int x = 0 ; x<limit;x++) {
System.out.println(x);
}
}
}
选择正确答案:
A.打印输出,从0至limit。
B.无内容输出,因为没有明确调用run()方法。
C.代码编译失败,因为没有正确实现Runnable接口。
D.代码编译失败,如果声明类为抽象类,可使代码编译成功。
E.代码编译失败,如果去掉implements Runnable,可使代码编译成功
C
public class Example {
public static void main(String[] args) {
Thread.sleep(3000);
System.out.println("sleep");
}
}
选中正确答案:
A.编译出错
B.运行时异常
C.正常编译运行,输出sleep
D.正常编译运行,但没有内容输出
A
(线程的创建)创建两个线程,要求如下:
I.一个线程输出100个1-26,另一个线程输出100个A-Z
II,一个线程使用继承Thread类的写法,另一个线程使用实现Runnable接口的写法。
public class TestThread {
public static void main(String[] args) {
MyThread1 t1 = new MyThread1();
t1.start();
Thread t2 = new Thread(new MyThread2());
t2.start();
}
}
class MyThread1 extends Thread{
@Override
public void run() {
for(int i = 0 ;i<100;i++) {
for(int j=1;j<=26;j++) {
System.out.print(j+" ");
}
System.out.println();
}
}
}
class MyThread2 implements Runnable{
@Override
public void run() {
char[] cr = "ABCDEFGHIJKLMNOPQRSTUVWSYZ".toCharArray();
for(int i = 0 ;i<100;i++) {
for(int j=0;j<cr.length;j++) {
System.out.print(cr[j]+" ");
}
System.out.println();
}
}
}
public class TestMyThread {
public static void main(String[] args) {
Object lock = new Object();
Thread t1 = new MyThread1(lock);
Thread t2 = new MyThread2(lock);
t1.start();
t2.start();
}
}
class MyThread1 extends Thread{
Object lock;
public MyThread1(Object lock) {
this.lock = lock;
}
public void run() {
synchronized(lock) {//1
for(int i = 0;i<=10;i++) {
try {
Thread.sleep((int)(Math.random()*1000));
}catch(Exception e) {}
System.out.println("$$$");
}
}
}
}
class MyThread2 extends Thread{
Object lock;
public MyThread2(Object lock) {
this.lock = lock;
}
public void run() {
synchronized(lock) {//2
for(int i = 0;i<=10;i++) {
try {
Thread.sleep((int)(Math.random()*1000));
}catch(Exception e) {}
System.out.println("###");
}
}
}
}
问:在//1和//2处加上的synchronized起什么作用?如果不加synchronized,运行程序有什么不同的地方?
当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。不加则是串行。
class MyThread extends Thread{
private String data;
public MyThread(String data) {
super();
this.data = data;
}
public void run() {
synchronized(data) {
for(int i = 0;i<10;i++) {
try {
Thread.sleep((int)(Math.random()*1000));
}catch(Exception e) {
}
System.out.println(data);
}
}
}
}
public class TestMyThread {
public static void main(String[] args) {
Thread t1 = new MyThread("hello");
Thread t2 = new MyThread("world");
t1.start();
t2.start();
}
}
问:上述代码输出的结果是什么?
A.先输出100个hello,然后是100个world
B.先输出100个world,然后是100个hello
C,线程不同步,因此交替输出hello和world
C
class MyThread extends Thread{
private String data;
public MyThread(String data) {
this.data = data;
}
public void run() {
for(int i = 0;i<100;i++) {
System.out.println(data);
}
}
}
public class TestMyThread {
public static void main(String[] args) {
Thread t1 = new MyThread("aaa");
Thread t2 = new MyThread("bbb");
t1.start();
t2.start();
}
}
现希望能够同步的输出aaa和bbb,即一次输出100个aaa或bbb,输出两个字符串时没有交互。为了达到上数目的,要对源代码进行修改。以下哪些修改方式能够得到想要的结果?
A.把第6行改为public synchronized void run()
B.把run方法中所有的内容都放在synchronized(data)代码中
C.把run方法中所以的内容都放在synchronized(System.data)代码中
C
class MyThread1 implements Runnable{
public void run() {
for(int i = 0;i<100;i++) {
this.sleep((int)(Math.random()*1000));
System.out.println("hello");
}
}
}
class MyThread2 extends Thread{
public void run() throws Exception{
for(int i = 0;i<100;i++) {
this.sleep((int)(Math.random()*1000));
System.out.println("world");
}
}
}
public class TestMyThread {
public static void main(String[] args) {
Runnable t1 = new MyThread1();
Thread t2 = new MyThread2();
t1.start();
t2.start();
}
}
class MyThread1 implements Runnable{
public void run() {
for(int i = 0;i<100;i++) {
//this.sleep((int)(Math.random()*1000));
try {
Thread.sleep((int)(Math.random()*1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hello");
}
}
}
class MyThread2 extends Thread{
public void run() /*throws Exception*/{
for(int i = 0;i<100;i++) {
try {
this.sleep((int)(Math.random()*1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("world");
}
}
}
public class TestMyThread {
public static void main(String[] args) {
//Runnable t1 = new MyThread1();
Thread t1 = new Thread(new MyThread1());
Thread t2 = new MyThread2();
t1.start();
t2.start();
}
}